org.fabrician.enabler.util.SpecialDirective.java Source code

Java tutorial

Introduction

Here is the source code for org.fabrician.enabler.util.SpecialDirective.java

Source

/*
 * Copyright (c) 2014 TIBCO Software Inc. All Rights Reserved.
 *
 * Use is subject to the terms of the TIBCO license terms accompanying the download of this code.
 * In most instances, the license terms are contained in a file named license.txt.
 */
package org.fabrician.enabler.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

import com.datasynapse.fabric.container.AbstractContainer;

/**
 * This class is used to resolve any special directive runtime context variable substitution tokens embedded in the string value of another runtime context variable. <code>
 * Example: HTTP_PORT=9000, !PORT_EXPOSE_xyz=80
 * !PORT_MAP_http1=${HTTP_PORT}:${!PORT_EXPOSE_xyz}
 * </code>
 * <p>
 * Above code will not be substituted for the substitution token ${!PORT_EXPOSE_xyz} because of the character (!) when using normal variables resolution. Instead, we use the following call to resolve
 * the embedded any special directive runtime context variable substitution tokens:
 * </p>
 * <code>
 * DockerContainer enabler =....
 * String http_port_map=SpecialDirective.resolveStringValue(enabler,"${HTTP_PORT}:${!PORT_EXPOSE_xyz}");
 * 
 * which should give us String http_port_map="9000:80"
 * </code>
 * 
 * Note: By convention, context variables that are prefixed by-
 * 
 * <pre>
 * "!PORT_EXPOSE_" are reckoned to be a private container ports to be exposed
 * "!PORT_MAP_" are reckoned to be a host-to-container ports mapping
 * "!VOL_MAP_" are reckoned to be a host-to-container volume mapping
 * "!ENV_VAR" are reckoned to be container enviromental variables mapping
 * "!ENV_FILE_" are reckoned to be container enviromental variables mapping
 * "!SEC_OPT_" are reckoned to be container security options
 * </pre>
 */
public enum SpecialDirective {
    PORT_EXPOSE("!PORT_EXPOSE_", "\\$\\{\\!PORT_EXPOSE_[a-zA-Z0-9_]+[a-zA-Z0-9_-]*\\}"), //
    PORT_MAP("!PORT_MAP_", "\\$\\{\\!PORT_MAP_[a-zA-Z0-9_]+[a-zA-Z0-9_-]*\\}"), //
    VOL_MAP("!VOL_MAP_", "\\$\\{\\!VOL_MAP_[a-zA-Z0-9_]+[a-zA-Z0-9_-]*\\}"), //
    ENV_VAR("!ENV_VAR_", "\\$\\{\\!ENV_VAR_[a-zA-Z0-9_]+[a-zA-Z0-9_-]*\\}"), //
    ENV_FILE("!ENV_FILE_", "\\$\\{\\!ENV_FILE_[a-zA-Z0-9_]+[a-zA-Z0-9_-]*\\}"), //
    SEC_OPT("!SEC_OPT_", "\\$\\{\\!SEC_OPT_[a-zA-Z0-9_]+[a-zA-Z0-9_-]*\\}");

    /**
     * Check if a string is prefixed by a special directive
     * 
     * @param str
     *            the string to check
     * @return true if prefixed; false otherwise
     */
    public boolean prefix(String str) {
        return str.startsWith(prefix);
    }

    /**
     * Return a list of prefixes represented by this enum
     * 
     * @return a list of prefixes
     */
    public static List<String> getPrefixes() {
        List<String> prefixes = new ArrayList<String>();
        for (SpecialDirective directive : values()) {
            prefixes.add(directive.prefix);
        }
        return Collections.unmodifiableList(prefixes);
    }

    /**
     * Resolve a string value including the special directive runtime context variables substitution tokens.
     * 
     * @param enabler
     *            the enabler use
     * @param str
     *            the string value
     * @return a fully resolved string value
     * @throws Exception
     */
    public static String resolveStringValue(AbstractContainer enabler, String str) throws Exception {
        if (StringUtils.trimToEmpty(str).isEmpty()) {
            return str;
        }
        String resolvedStr = enabler.resolveVariables(str);
        List<String> substitution_tokens = extractSubstitutionTokens(resolvedStr);
        if (substitution_tokens.isEmpty()) {
            return resolvedStr;
        }
        Map<String, String> resolutionMap = resolveSubstitutionTokens(enabler, substitution_tokens);
        resolvedStr = StringUtils.replaceEachRepeatedly(resolvedStr, substitution_tokens.toArray(new String[] {}),
                getReplacementValues(substitution_tokens, resolutionMap));
        return resolvedStr;
    }

    /**
     * Extract the list of 'Special Directive' runtime context variable substitution tokens embedded in a String
     * 
     * @param str
     *            the string to extract from
     * @return a List of substitution tokens.
     */
    public static List<String> extractSubstitutionTokens(String str) {
        List<String> list = new ArrayList<String>();
        if (StringUtils.trimToEmpty(str).isEmpty()) {
            return Collections.unmodifiableList(list);
        }
        for (SpecialDirective directive : list()) {
            Matcher m = directive.substitutionPattern.matcher(str);
            if (m.find()) {
                String substring = m.group(0);
                if (substring != null && !list.contains(substring)) {
                    list.add(substring);
                }
            }
        }
        return Collections.unmodifiableList(list);
    }

    private static List<SpecialDirective> list() {
        return Arrays.asList(values());
    }

    private static Map<String, String> resolveSubstitutionTokens(AbstractContainer enabler,
            List<String> substitutionTokens) {
        Map<String, String> resolvedMap = new HashMap<String, String>();
        for (String subToken : substitutionTokens) {
            try {
                String contextVar = subToken.substring(2, subToken.length() - 1); // assume ${XYZ} where XYZ == the contextVar
                String contextVarValue = enabler.getStringVariableValue(contextVar);
                String resolvedVarValue = enabler.resolveVariables(contextVarValue);
                List<String> specialSubstitutions2 = extractSubstitutionTokens(resolvedVarValue);
                if (specialSubstitutions2.isEmpty()) {
                    resolvedMap.put(subToken, resolvedVarValue);
                } else {
                    Map<String, String> resolvedMap2 = resolveSubstitutionTokens(enabler, specialSubstitutions2);
                    String resolvedVarValue2 = StringUtils.replaceEachRepeatedly(resolvedVarValue,
                            specialSubstitutions2.toArray(new String[] {}),
                            getReplacementValues(specialSubstitutions2, resolvedMap2));
                    resolvedMap.put(subToken, resolvedVarValue2);
                }
            } catch (Exception ex) {

            }
        }
        return Collections.unmodifiableMap(resolvedMap);
    }

    private static String[] getReplacementValues(List<String> substitutionTokens,
            Map<String, String> substitutionTokenValueMap) {
        List<String> values = new ArrayList<String>();
        for (String token : substitutionTokens) {
            values.add(substitutionTokenValueMap.get(token));
        }
        return values.toArray(new String[] {});
    }

    private SpecialDirective(final String prefix, final String substitutionPattern) {
        this.prefix = prefix;
        this.substitutionPattern = Pattern.compile(substitutionPattern);
    }

    private final String prefix;
    private final Pattern substitutionPattern;

}