class AppConfig {

    private static final Logger log = LoggerFactory.getLogger(AppConfig.class);
    private static PropertiesConfiguration prop;
    public static final String CONFIG_DIR = StringUtils.isNotEmpty(System.getProperty("CONFIG_DIR")) ? System.getProperty("CONFIG_DIR").trim() : AppConfig.class.getClassLoader().getResource(".").getPath();

    static {
        try {
            //move configuration to specified dir
            if (StringUtils.isNotEmpty(System.getProperty("CONFIG_DIR"))) {
                File configFile = new File(CONFIG_DIR + "BastillionConfig.properties");
                if (!configFile.exists()) {
                    File oldConfig = new File(AppConfig.class.getClassLoader().getResource(".").getPath() + "BastillionConfig.properties");
                    FileUtils.moveFile(oldConfig, configFile);
                }
                configFile = new File(CONFIG_DIR + "jaas.conf");
                if (!configFile.exists()) {
                    File oldConfig = new File(AppConfig.class.getClassLoader().getResource(".").getPath() + "jaas.conf");
                    FileUtils.moveFile(oldConfig, configFile);
                }
            }
            prop = new PropertiesConfiguration(CONFIG_DIR + "BastillionConfig.properties");
        } catch (IOException | ConfigurationException ex) {
            log.error(ex.toString(), ex);
        }
    }

    private AppConfig() {
    }

    /**
     * gets the property from config
     *
     * @param name property name
     * @return configuration property
     */
    public static String getProperty(String name) {
        String property = null;
        if (StringUtils.isNotEmpty(name)) {
            if (StringUtils.isNotEmpty(System.getenv(name))) {
                property = System.getenv(name);
            } else if (StringUtils.isNotEmpty(System.getenv(name.toUpperCase()))) {
                property = System.getenv(name.toUpperCase());
            } else {
                property = prop.getString(name);
            }
        }
        return property;

    }

    /**
     * gets the property from config
     *
     * @param name         property name
     * @param defaultValue default value if property is empty
     * @return configuration property
     */
    public static String getProperty(String name, String defaultValue) {
        String value = getProperty(name);
        if (StringUtils.isEmpty(value)) {
            value = defaultValue;
        }
        return value;
    }

    /**
     * gets the property from config and replaces placeholders
     *
     * @param name           property name
     * @param replacementMap name value pairs of place holders to replace
     * @return configuration property
     */
    public static String getProperty(String name, Map<String, String> replacementMap) {

        String value = getProperty(name);
        if (StringUtils.isNotEmpty(value)) {
            //iterate through map to replace text
            Set<String> keySet = replacementMap.keySet();
            for (String key : keySet) {
                //replace values in string
                String rVal = replacementMap.get(key);
                value = value.replace("${" + key + "}", rVal);
            }
        }
        return value;
    }

    /**
     * removes property from the config
     *
     * @param name property name
     */
    public static void removeProperty(String name) throws ConfigurationException {

        //remove property
        prop.clearProperty(name);
        prop.save();

    }

    /**
     * updates the property in the config
     *
     * @param name  property name
     * @param value property value
     */
    public static void updateProperty(String name, String value) throws ConfigurationException {
        //remove property
        if (StringUtils.isNotEmpty(value)) {
            prop.setProperty(name, value);
            prop.save();
        }
    }


    /**
     * checks if property is encrypted
     *
     * @param name property name
     * @return true if property is encrypted
     */
    public static boolean isPropertyEncrypted(String name) {
        String property = prop.getString(name);
        if (StringUtils.isNotEmpty(property)) {
            return property.matches("^" + EncryptionUtil.CRYPT_ALGORITHM + "\\{.*\\}$");
        } else {
            return false;
        }
    }

    /**
     * decrypts and returns the property from config
     *
     * @param name property name
     * @return configuration property
     */
    public static String decryptProperty(String name) throws GeneralSecurityException {<FILL_FUNCTION_BODY>}

    /**
     * encrypts and updates the property in the config
     *
     * @param name  property name
     * @param value property value
     */
    public static void encryptProperty(String name, String value) throws ConfigurationException, GeneralSecurityException {
        //remove property
        if (StringUtils.isNotEmpty(value)) {
            prop.setProperty(name, EncryptionUtil.CRYPT_ALGORITHM + "{" + EncryptionUtil.encrypt(value) + "}");
            prop.save();
        }
    }


}

        String retVal = prop.getString(name);
        if (StringUtils.isNotEmpty(retVal)) {
            retVal = retVal.replaceAll("^" + EncryptionUtil.CRYPT_ALGORITHM + "\\{", "").replaceAll("\\}$", "");
            retVal = EncryptionUtil.decrypt(retVal);
        }
        return retVal;
    
<no_super_class>