/*
cs *   Licensed to the Apache Software Foundation (ASF) under one
 *   or more contributor license agreements.  See the NOTICE file
 *   distributed with this work for additional information
 *   regarding copyright ownership.  The ASF licenses this file
 *   to you under the Apache License, Version 2.0 (the
 *   "License"); you may not use this file except in compliance
 *   with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing,
 *   software distributed under the License is distributed on an
 *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *   KIND, either express or implied.  See the License for the
 *   specific language governing permissions and limitations
 *   under the License.
 *
 */
package org.apache.directory.fortress.core.util;


import java.net.URL;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.lang.StringUtils;
import org.apache.directory.fortress.core.CfgException;
import org.apache.directory.fortress.core.CfgRuntimeException;
import org.apache.directory.fortress.core.ConfigMgr;
import org.apache.directory.fortress.core.ConfigMgrFactory;
import org.apache.directory.fortress.core.GlobalErrIds;
import org.apache.directory.fortress.core.GlobalIds;
import org.apache.directory.fortress.core.SecurityException;
import org.apache.directory.fortress.core.model.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class wraps <a href="http://commons.apache.org/cfg/">Apache Commons Config</a> utility and is used by internal components to retrieve name-value
 * pair properties from its cfg context.  The class will combine properties that it finds in its local property
 * file along with data that is retrieved by name from the ldap server if name is specified within
 * the {@link org.apache.directory.fortress.core.GlobalIds#CONFIG_REALM} switch.
 * <p>
 * The class will bootstrap itself during startup and must initialize correctly for the Fortress APIs to work correctly.
 * <p>
 * This object is thread safe but stores a static reference to Apache Commons Configuration {@link #config} object.
 * <p>
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public final class Config
{
    private static PropertiesConfiguration config = new PropertiesConfiguration();
    private static final String CLS_NM = Config.class.getName();
    private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
    private static final String PROP_FILE = "fortress.properties";
    private static final String USER_PROP_FILE = "fortress.user.properties";
    private static final String EXT_LDAP_HOST = "fortress.host";
    private static final String EXT_LDAP_PORT = "fortress.port";
    private static final String EXT_LDAP_ADMIN_POOL_UID = "fortress.admin.user";
    private static final String EXT_LDAP_ADMIN_POOL_PW = "fortress.admin.pw";
    private static final String EXT_LDAP_ADMIN_POOL_MIN = "fortress.min.admin.conn";
    private static final String EXT_LDAP_ADMIN_POOL_MAX = "fortress.max.admin.conn";
    private static final String EXT_LDAP_LOG_POOL_UID = "fortress.log.user";
    private static final String EXT_LDAP_LOG_POOL_PW = "fortress.log.pw";
    private static final String EXT_LDAP_LOG_POOL_MIN = "fortress.min.log.conn";
    private static final String EXT_LDAP_LOG_POOL_MAX = "fortress.max.log.conn";
    private static final String EXT_ENABLE_LDAP_SSL = "fortress.enable.ldap.ssl";
    private static final String EXT_ENABLE_LDAP_STARTTLS = "fortress.enable.ldap.starttls";
    private static final String EXT_ENABLE_LDAP_SSL_DEBUG = "fortress.enable.ldap.ssl.debug";
    private static final String EXT_TRUST_STORE = "fortress.trust.store";
    private static final String EXT_TRUST_STORE_PW = "fortress.trust.store.password";
    private static final String EXT_TRUST_STORE_ONCLASSPATH = "fortress.trust.store.onclasspath";
    private static final String EXT_CONFIG_REALM = "fortress.config.realm";
    private static final String EXT_CONFIG_ROOT_DN = "fortress.config.root";
    private static final String EXT_SERVER_TYPE = "fortress.ldap.server.type";
    private static final String EXT_IS_ARBAC02 = "fortress.is.arbac02";

    // static reference contains this.
    private static volatile Config sINSTANCE = null;

    // used internally to determine if the remote config has been loaded.
    private boolean remoteConfigLoaded = false;

    /**
     * Return a static reference to this instance.  If the instance has not been instantiated, call the boostrap:
     * <ul>
     *     <li>Load from fortress.properties</li>
     *     <li>Load some overrides from System properties</li>
     *     <li>Load from ou=Config ldap node</li>
     * </ul>
     *
     * @return this
     */
    public static Config getInstance()
    {
        if(sINSTANCE == null)
        {
            synchronized (Config.class)
            {
                if(sINSTANCE == null)
                {
                    sINSTANCE = new Config();
                    if( !sINSTANCE.isRemoteConfigLoaded() )
                    {
                        sINSTANCE.loadRemoteConfig();
                    }
                }
            }
        }
        return sINSTANCE;
    }

    /**
     * Private constructor called during bootstrap sequence of this class.
     *
     */
    private Config()
    {
        // Load from properties file:
        loadLocalConfig();
        // load the system property overrides:
        getExternalConfig();
    }

    /**
     * Gets the prop attribute as String value from the apache commons cfg component.
     *
     * @param name contains the name of the property.
     * @return contains the value associated with the property or null if not not found.
     */
    public String getProperty( String name )
    {
        return getProperty( name, false );
    }

    /**
     * Gets the prop attribute as String value from the apache commons cfg component.
     *
     * @param name contains the name of the property.
     * @param nologvalue if true will not output this prop's value to the debug logger.
     * @return contains the value associated with the property or null if not not found.
     */
    public String getProperty( String name, boolean nologvalue )
    {
        String value = null;
        if ( config != null )
        {
            value = ( String ) config.getProperty( name );
            LOG.debug( "getProperty name [{}] value [{}]", name, nologvalue ? "****" : value );
        }
        else
        {
            LOG.warn( "getProperty invalid config, can't read prop [{}]", name );
        }
        return value;
    }

    /**
     * Get the property value from the apache commons config but specify a default value if not found.
     *
     * @param name         contains the name of the property.
     * @param defaultValue specified by client will be returned if property value is not found.
     * @return contains the value for the property as a String.
     */
    public String getProperty( String name, String defaultValue )
    {
        String value = null;
        if ( config != null )
        {
            value = ( String ) config.getProperty( name );
            LOG.debug( "getProperty name [{}] value [{}] default value [{}]", name, value, defaultValue );
        }
        else
        {
            String warn = "getProperty invalid config, can't read prop [" + name + "]";
            LOG.warn( warn );
        }
        if ( value == null || value.length() == 0 )
        {
            value = defaultValue;
        }
        return value;
    }

    /**
     * Gets the prop attribute as char value from the apache commons cfg component.
     *
     * @param name contains the name of the property.
     * @return contains the value associated with the property or 0 if not not found.
     */
    public char getChar( String name )
    {
        char value = 0;
        if ( config != null )
        {
            value = ( char ) config.getProperty( name );
            LOG.debug( "getChar name [{}] value [{}]", name, value );
        }
        else
        {
            LOG.warn( "getChar invalid config, can't read prop [{}]", name );
        }
        return value;
    }

    /**
     * Get the property value from the apache commons config but specify a default value if not found.
     *
     * @param name         contains the name of the property.
     * @param defaultValue specified by client will be returned if property value is not found.
     * @return contains the value for the property as a char.
     */
    public char getChar( String name, char defaultValue )
    {
        char value = 0;
        if ( config != null )
        {
            value = ( char ) config.getProperty( name );
            LOG.debug( "getChar name [{}] value [{}]", name, value );
        }
        else
        {
            LOG.warn( "getChar invalid config, can't read prop [{}], using default [{}]", name, defaultValue );
        }
        if ( value == 0 )
        {
            value = defaultValue;
        }
        return value;
    }

    /**
     * Gets the int attribute of the Config class, or 0 if not found.
     *
     * @param key name of the property name.
     * @return The int value or 0 if not found.
     */
    public int getInt( String key )
    {
        int value = 0;
        try
        {
            if ( config != null )
            {
                value = config.getInt( key );
                LOG.debug( "getInt name [{}] value [{}]", key, value );
            }
            else
            {
                LOG.warn( "getInt invalid config, can't read prop [{}]", key );
            }
        }
        catch (org.apache.commons.configuration.ConversionException e)
        {
            LOG.debug( "getInt can't read prop [{}], exception [{}]", key, e );
        }
        return value;
    }

    /**
     * Gets the int attribute of the Config class or default value if not found.
     *
     * @param key          name of the property name.
     * @param defaultValue to use if property not found.
     * @return The int value or default value if not found.
     */
    public int getInt( String key, int defaultValue )
    {
        int value = defaultValue;
        try
        {
            if ( config != null )
            {
                value = config.getInt( key, defaultValue );
                LOG.debug( "getInt name [{}] value [{}]", key, value );
            }
            else
            {
                LOG.warn( "getInt invalid config, can't read prop [{}], using default [{}]", key, defaultValue );

            }
        }
        catch (org.apache.commons.configuration.ConversionException e)
        {
            LOG.debug( "getInt can't read prop [{}], using default [{}], exception [{}]", key, defaultValue, e );
        }
        return value;
    }

    /**
     * Gets the boolean attribute associated with the name or false if not found.
     *
     * @param key name of the property name.
     * @return The boolean value or false if not found.
     */
    public boolean getBoolean( String key )
    {
        boolean value = false;
        try
        {
            if (config != null)
            {
                value = config.getBoolean(key);
                LOG.debug( "getBoolean name [{}] value [{}]", key, value );
            }
            else
            {
                LOG.warn( "getBoolean invalid config, can't read prop [{}], using default [{}]", key, false );

            }
        }
        catch (java.util.NoSuchElementException e )
        {
            LOG.debug( "getBoolean - no such element [{}], using default [{}]", key, false );
        }
        return value;
    }

    /**
     * Gets the boolean attribute associated with the name or false if not found.
     *
     * @param key          name of the property name.
     * @param defaultValue specified by client will be returned if property value is not found.
     * @return The boolean value or false if not found.
     */
    public boolean getBoolean( String key, boolean defaultValue )
    {
        boolean value = defaultValue;
        try
        {
            if ( config != null )
            {
                value = config.getBoolean( key, defaultValue );
                LOG.debug( "getBoolean name [{}] value [{}]", key, value );
            }
            else
            {
                LOG.warn( "getBoolean - invalid config, can't read prop [{}], using default [{}]", key, defaultValue );
            }
        }
        catch (java.util.NoSuchElementException e )
        {
            LOG.debug( "getBoolean - no such element [{}], using default [{}]", key, defaultValue );
        }
        return value;
    }

    /**
     * Set the property String value to the apache commons config.
     *
     * @param name         contains the name of the property.
     * @param value        contains the String value of the property.
     */
    public void setProperty( String name, String value )
    {
        if ( config != null )
        {
            config.setProperty( name, value );
        }
        else
        {
            LOG.warn( "setProperty invalid config, can't set prop name [{}], value [{}]" + name, value);
        }
    }

    /**
     * Clear the property from apache commons config.
     *
     * @param name  contains the name of the property.
     */
    public void clearProperty( String name )
    {
        if ( config != null )
        {
            config.clearProperty( name );
        }
        else
        {
            LOG.warn( "clearProperty invalid config, prop name [{}]", name );
        }
    }

    /**
     * Fetch the remote cfg params from ldap with given name.
     *
     * @param realmName required attribute contains the name of config node name on ldap.
     * @return {@link Properties} containing collection of name/value pairs found in directory.
     * @throws org.apache.directory.fortress.core.SecurityException
     *          in the event of system or validation error.
     */
    private Properties getRemoteConfig( String realmName ) throws SecurityException
    {
        Properties props = null;
        try
        {
            String configClassName = this.getProperty( GlobalIds.CONFIG_IMPLEMENTATION );
            ConfigMgr cfgMgr = ConfigMgrFactory.createInstance(configClassName, false);
            Configuration configuration = cfgMgr.read( realmName );
            props = configuration.getProperties();
        }
        catch ( CfgException ce )
        {
            if ( ce.getErrorId() == GlobalErrIds.FT_CONFIG_NOT_FOUND )
            {
                LOG.warn( "getRemoteConfig could not find cfg entry [{}]", realmName );
            }
            else
            {
                throw ce;
            }
        }
        return props;
    }

    public boolean isRestEnabled()
    {
        return ( ( getProperty( GlobalIds.ENABLE_REST ) != null ) && ( getProperty( GlobalIds.ENABLE_REST ).equalsIgnoreCase( "true" ) ) );
    }
    /**
     * Fortress stores complex attribute types within a single attribute in ldap.  Usually a delimiter of '$' is used for string tokenization.
     * format: {@code part1$part2$part3....}  Stored in fortress.properties as 'attr.delimiter=$'
     */
    public String getDelimiter()
    {
        return getProperty( "attr.delimiter", "$" );
    }
    public boolean isAuditDisabled()
    {
        return ( ( getProperty( GlobalIds.DISABLE_AUDIT ) != null ) && ( getProperty( GlobalIds.DISABLE_AUDIT ).equalsIgnoreCase( "true" ) ) );
    }
    public boolean isOpenldap()
    {
        return ( ( getProperty( GlobalIds.SERVER_TYPE ) != null ) && ( getProperty( GlobalIds.SERVER_TYPE ).equalsIgnoreCase( "openldap" ) ) );
    }
    public boolean isApacheds()
    {
        return ( ( getProperty( GlobalIds.SERVER_TYPE ) != null ) && ( getProperty( GlobalIds.SERVER_TYPE ).equalsIgnoreCase( "apacheds" ) ) );
    }
    public boolean isRealm()
    {
        return GlobalIds.REALM_TYPE.equalsIgnoreCase( getProperty( GlobalIds.AUTHENTICATION_TYPE ) );
    }
    public boolean isRoleOccupant()
    {
        // misc LDAP:
        String ROLE_OCCUPANTS = "role.occupants";

        // default is true:
        boolean result = true;
        if(( ( getProperty( ROLE_OCCUPANTS ) != null ) && ( getProperty( ROLE_OCCUPANTS ).equalsIgnoreCase( "false" ) ) ))
            result = false;
        return result;
    }

    private boolean isRemoteConfigLoaded()
    {
        return remoteConfigLoaded;
    }

    private char[] loadLdapEscapeChars()
    {
        char[] ldapMetaChars = new char[LdapUtil.getInstance().getLdapFilterSize()];

        for ( int i = 1;; i++ )
        {
            String prop = GlobalIds.LDAP_FILTER + i;
            String value = getProperty( prop );

            if ( value == null )
            {
                break;
            }

            ldapMetaChars[i - 1] = value.charAt( 0 );
        }

        return ldapMetaChars;
    }

    private String[] loadValidLdapVals()
    {
        String[] ldapReplacements = new String[LdapUtil.getInstance().getLdapFilterSize()];

        for ( int i = 1;; i++ )
        {
            String prop = GlobalIds.LDAP_SUB + i;
            String value = getProperty( prop );

            if ( value == null )
            {
                break;
            }

            ldapReplacements[i - 1] = value;
        }

        return ldapReplacements;
    }

    /**
     * Load the config parameters from fortress.properties file.
     */
    private void loadLocalConfig()
    {
        try
        {
            // Load the system config file.
            URL fUrl = Config.class.getClassLoader().getResource( PROP_FILE );
            config.setDelimiterParsingDisabled( true );
            if ( fUrl == null )
            {
                String error = "static init: Error, null cfg file: " + PROP_FILE;
                LOG.warn( error );
            }
            else
            {
                LOG.info( "static init: found from: {} path: {}", PROP_FILE, fUrl.getPath() );
                config.load( fUrl );
                LOG.info( "static init: loading from: {}", PROP_FILE );
            }

            URL fUserUrl = Config.class.getClassLoader().getResource( USER_PROP_FILE );
            if ( fUserUrl != null )
            {
                LOG.info( "static init: found user properties from: {} path: {}", USER_PROP_FILE, fUserUrl.getPath() );
                config.load( fUserUrl );
            }
        }
        catch ( org.apache.commons.configuration.ConfigurationException ex )
        {
            String error = "static init: Error loading from cfg file: [" + PROP_FILE
                + "] ConfigurationException=" + ex;
            LOG.error( error );
            throw new CfgRuntimeException( GlobalErrIds.FT_CONFIG_BOOTSTRAP_FAILED, error, ex );
        }
    }

    /**
     * Load these config parameters from the system.properties.
     */
    private void getExternalConfig()
    {
        String PREFIX = "getExternalConfig override name [{}] value [{}]";
        // Check to see if the ldap host has been overridden by a system property:
        String szValue = System.getProperty( EXT_LDAP_HOST );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.LDAP_HOST, szValue );
            LOG.info( PREFIX, GlobalIds.LDAP_HOST, szValue );
        }
        // Check to see if the ldap port has been overridden by a system property:
        szValue = System.getProperty( EXT_LDAP_PORT );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.LDAP_PORT, szValue );
            LOG.info( PREFIX, GlobalIds.LDAP_PORT, szValue );
        }

        // Check to see if the admin pool uid has been overridden by a system property:
        szValue = System.getProperty( EXT_LDAP_ADMIN_POOL_UID );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.LDAP_ADMIN_POOL_UID, szValue );
            // never display ldap admin userid name to log:
            LOG.info( "getExternalConfig override name [{}]", GlobalIds.LDAP_ADMIN_POOL_UID );
        }

        // Check to see if the admin pool pw has been overridden by a system property:
        szValue = System.getProperty( EXT_LDAP_ADMIN_POOL_PW );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.LDAP_ADMIN_POOL_PW, szValue );
            // never display password of any type to log:
            LOG.info( "getExternalConfig override name [{}]", GlobalIds.LDAP_ADMIN_POOL_PW );
        }

        // Check to see if the admin pool min connections has been overridden by a system property:
        szValue = System.getProperty( EXT_LDAP_ADMIN_POOL_MIN );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.LDAP_ADMIN_POOL_MIN, szValue );
            LOG.info( PREFIX, GlobalIds.LDAP_ADMIN_POOL_MIN, szValue );
        }

        // Check to see if the admin pool max connections has been overridden by a system property:
        szValue = System.getProperty( EXT_LDAP_ADMIN_POOL_MAX );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.LDAP_ADMIN_POOL_MAX, szValue );
            LOG.info( PREFIX, GlobalIds.LDAP_ADMIN_POOL_MAX, szValue );
        }

        // Check to see if the log pool uid has been overridden by a system property:
        szValue = System.getProperty( EXT_LDAP_LOG_POOL_UID );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.LDAP_LOG_POOL_UID, szValue );
            // never display ldap admin userid name to log:
            LOG.info( "getExternalConfig override name [{}]", GlobalIds.LDAP_LOG_POOL_UID );
        }

        // Check to see if the log pool pw has been overridden by a system property:
        szValue = System.getProperty( EXT_LDAP_LOG_POOL_PW );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.LDAP_LOG_POOL_PW, szValue );
            // never display password of any type to log:
            LOG.info( "getExternalConfig override name [{}]", GlobalIds.LDAP_LOG_POOL_PW );
        }

        // Check to see if the log pool min connections has been overridden by a system property:
        szValue = System.getProperty( EXT_LDAP_LOG_POOL_MIN );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.LDAP_LOG_POOL_MIN, szValue );
            LOG.info( PREFIX, GlobalIds.LDAP_LOG_POOL_MIN, szValue );
        }

        // Check to see if the log pool max connections has been overridden by a system property:
        szValue = System.getProperty( EXT_LDAP_LOG_POOL_MAX );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.LDAP_LOG_POOL_MAX, szValue );
            LOG.info( PREFIX, GlobalIds.LDAP_LOG_POOL_MAX, szValue );
        }

        // Check to see if ssl enabled parameter has been overridden by a system property:
        szValue = System.getProperty( EXT_ENABLE_LDAP_SSL );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.ENABLE_LDAP_SSL, szValue );
            LOG.info( PREFIX, GlobalIds.ENABLE_LDAP_SSL, szValue );
        }
        
        // Check to see if start tls enabled parameter has been overridden by a system property:
        szValue = System.getProperty( EXT_ENABLE_LDAP_STARTTLS );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.ENABLE_LDAP_STARTTLS, szValue );
            LOG.info( PREFIX, GlobalIds.ENABLE_LDAP_STARTTLS, szValue );
        }

        // Check to see if the ssl debug enabled parameter has been overridden by a system property:
        szValue = System.getProperty( EXT_ENABLE_LDAP_SSL_DEBUG );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.ENABLE_LDAP_SSL_DEBUG, szValue );
            LOG.info( PREFIX, GlobalIds.ENABLE_LDAP_SSL_DEBUG, szValue );
        }

        // Check to see if the trust store location has been overridden by a system property:
        szValue = System.getProperty( EXT_TRUST_STORE );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.TRUST_STORE, szValue );
            LOG.info( PREFIX, GlobalIds.TRUST_STORE, szValue );
        }

        // Check to see if the trust store password has been overridden by a system property:
        szValue = System.getProperty( EXT_TRUST_STORE_PW );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.TRUST_STORE_PW, szValue );
            // never display password value to log:
            LOG.info( "getExternalConfig override name [{}]", GlobalIds.TRUST_STORE_PW );
        }

        // Check to see if the trust store onclasspath parameter has been overridden by a system property:
        szValue = System.getProperty( EXT_TRUST_STORE_ONCLASSPATH );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.TRUST_STORE_ON_CLASSPATH, szValue );
            LOG.info( PREFIX, GlobalIds.TRUST_STORE_ON_CLASSPATH, szValue );
        }

        // Check to see if the config realm name has been overridden by a system property:
        szValue = System.getProperty( EXT_CONFIG_REALM );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.CONFIG_REALM, szValue );
            LOG.info( PREFIX, GlobalIds.CONFIG_REALM, szValue );
        }

        // Check to see if the config realm name has been overridden by a system property:
        szValue = System.getProperty( EXT_CONFIG_ROOT_DN );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.CONFIG_ROOT_PARAM, szValue );
            LOG.info( PREFIX, GlobalIds.CONFIG_ROOT_PARAM, szValue );
        }

        // Check to see if the ldap server type has been overridden by a system property:
        szValue = System.getProperty( EXT_SERVER_TYPE  );
        if( StringUtils.isNotEmpty( szValue ))
        {
            config.setProperty( GlobalIds.SERVER_TYPE, szValue );
            LOG.info( PREFIX, GlobalIds.SERVER_TYPE, szValue );
        }

        // Check to see if ARBAC02 checking enforced in service layer:
        szValue = System.getProperty( EXT_IS_ARBAC02 );
        LOG.info( PREFIX, GlobalIds.IS_ARBAC02, szValue );

        if( StringUtils.isNotEmpty( szValue ))
        {
            Boolean isArbac02 = new Boolean(szValue);
            config.setProperty( GlobalIds.IS_ARBAC02, isArbac02.booleanValue() );
            LOG.info( PREFIX, GlobalIds.IS_ARBAC02, isArbac02.booleanValue() );
        }
    }

    /**
     * Load the properties contained within ou=Config node in LDAP.
     */
    private void loadRemoteConfig()
    {
        try
        {
            // Retrieve parameters from the config node stored in target LDAP DIT:
            String realmName = config.getString( GlobalIds.CONFIG_REALM, "DEFAULT" );
            if ( realmName != null && realmName.length() > 0 )
            {
                LOG.info( "static init: load config realm [{}]", realmName );
                Properties props = getRemoteConfig( realmName );
                if ( props != null )
                {
                    for ( Enumeration<?> e = props.propertyNames(); e.hasMoreElements(); )
                    {
                        String key = ( String ) e.nextElement();
                        String val = props.getProperty( key );
                        config.setProperty( key, val );
                    }
                }

                //init ldap util vals since config is stored on server
                boolean ldapfilterSizeFound = ( getProperty( GlobalIds.LDAP_FILTER_SIZE_PROP ) != null );
                LdapUtil.getInstance().setLdapfilterSizeFound(ldapfilterSizeFound);
                LdapUtil.getInstance().setLdapMetaChars( loadLdapEscapeChars() );
                LdapUtil.getInstance().setLdapReplVals( loadValidLdapVals() );
                try
                {
                    String lenProp = getProperty( GlobalIds.LDAP_FILTER_SIZE_PROP );
                    if ( ldapfilterSizeFound )
                    {
                        LdapUtil.getInstance().setLdapFilterSize(Integer.valueOf( lenProp ));
                    }
                }
                catch ( java.lang.NumberFormatException nfe )
                {
                    String error = "loadRemoteConfig caught NumberFormatException=" + nfe;
                    LOG.warn( error );
                }
                remoteConfigLoaded = true;
            }
            else
            {
                LOG.info( "static init: config realm not setup" );
            }
        }
        catch ( SecurityException se )
        {
            String error = "static init: Error loading from remote config: SecurityException="
                + se;
            LOG.error( error );
            throw new CfgRuntimeException( GlobalErrIds.FT_CONFIG_INITIALIZE_FAILED, error, se );
        }
    }

    /**
     * Constructs a key used to store dynamic role constraints inside the properties, as name:value.
     * The key format is: RC$contextId$role
     * @param role contains the name of the role being constrained.
     * @param contextId contains the tenant name.
     * @return String containing the key name used to lookup the value of the role constraint.
     */
    public String getConstraintKey( String role, String contextId )
    {
        return GlobalIds.CONSTRAINT_KEY_PREFIX +
                getDelimiter() +
                contextId +
                getDelimiter()
                + role.toLowerCase();
    }

    /**
     * Performs auto-increment on a list of key names that map to integer values stored on the current config node of the runtime.
     * Unfortunately, it's synchronized to prevent a race condition of multiple threads trying to update the same id.
     * Worse, it doesn't lock meaning not synched across processes and so a temporary workaround until the pending Apache LDAP API/Directory support for RFC 4525 (Modify Increment attribute).
     *
     * @param props list of attribute names to update on config node.
     * @param propUpdater reference to object that updates to new value.
     * @return Configuration entity containing the old values.
     */
    public synchronized Configuration getIncrementReplacePosixIds(List<String> props, PropUpdater propUpdater ) throws CfgException
    {
        String cfgName = Config.getInstance().getProperty( GlobalIds.CONFIG_REALM, "DEFAULT" );
        org.apache.directory.fortress.core.model.Configuration inConfig;
        try
        {
            ConfigMgr cfgMgr = ConfigMgrFactory.createInstance();
            inConfig = cfgMgr.getIds( cfgName );
            org.apache.directory.fortress.core.model.Configuration outConfig = new Configuration();
            outConfig.setName( cfgName );
            for( String name : props )
            {
                if( name.equals( GlobalIds.UID_NUMBER ) )
                {
                    outConfig.setUidNumber( propUpdater.newValue( inConfig.getUidNumber() ) );
                }
                if( name.equals( GlobalIds.GID_NUMBER ) )
                {
                    outConfig.setGidNumber( propUpdater.newValue( inConfig.getGidNumber() ) );
                }
            }
            cfgMgr.update( outConfig );
        }
        catch ( SecurityException se )
        {
            String error = "replaceProperty failed, exception=" + se.getMessage();
            throw new CfgRuntimeException( GlobalErrIds.FT_CONFIG_UPDATE_FAILED, error, se );
        }
        return inConfig;
    }
}