com.aol.advertising.qiao.config.AgentXmlConfiguration.java Source code

Java tutorial

Introduction

Here is the source code for com.aol.advertising.qiao.config.AgentXmlConfiguration.java

Source

/****************************************************************************
 * Copyright (c) 2015 AOL Inc.
 * @author:     ytung05
 *
 * Licensed 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 com.aol.advertising.qiao.config;

import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.configuration.CombinedConfiguration;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.OverrideCombiner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aol.advertising.qiao.config.PropertyValue.DataType;
import com.aol.advertising.qiao.config.PropertyValue.Type;
import com.aol.advertising.qiao.config.QiaoConfig.FunnelComponents;
import com.aol.advertising.qiao.exception.ConfigurationException;
import com.aol.advertising.qiao.util.CommonUtils;
import com.aol.advertising.qiao.util.XmlConfigUtil;

/**
 * AgentXmlConfiguration parses application's qiao.xml and loads configuration
 * parameters for all the defined components.
 */
public class AgentXmlConfiguration implements IAgentXmlConfig {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    protected String configXmlFileUri;
    protected String configPropertyFiles;
    protected String schemaLocationUri = "classpath:qiao-config.xsd";
    protected HierarchicalConfiguration xmlConfig;

    protected QiaoConfig qiaoConfig;

    @Override
    public void load() throws ConfigurationException {
        boolean valid = XmlConfigUtil.validateXml(configXmlFileUri, schemaLocationUri);

        if (!valid)
            throw new ConfigurationException("Invalid Qiao configuration file: " + configXmlFileUri);

        xmlConfig = readConfigurationFiles(configXmlFileUri, configPropertyFiles);

        logger.info(configXmlFileUri + " loaded");

        loadQiaoConfig();
    }

    private void loadQiaoConfig() {
        qiaoConfig = new QiaoConfig();

        MultiSubnodeConfiguration tmp = loadMutiNodeConfigAndProperties(ConfigConstants.CFGKEY_FUNNEL);
        if (tmp == null) {
            logger.warn(ConfigConstants.CFGKEY_FUNNEL + " not configured");
        } else {
            qiaoConfig.setFunnelConfig(tmp);
            Map<String, String> classnames = getClassNames(tmp);
            qiaoConfig.setFunnelClassNames(classnames);

            Map<String, FunnelComponents> mcomponents = new HashMap<String, FunnelComponents>();
            for (int i = 0; i < tmp.size(); i++) {
                FunnelComponents fc = qiaoConfig.new FunnelComponents();

                fc.setSourceConfig(loadSourceConfig(i));
                fc.setSinkConfig(loadSinkConfig(i));
                fc.setId(tmp.get(i).getId());
                mcomponents.put(fc.getId(), fc);
            }

            qiaoConfig.setFunnelComponents(mcomponents);
        }
    }

    protected InjectorConfig loadSourceConfig(int idx) {
        String node_idx = String.format(ConfigConstants.CFGKEY_FUNNEL_INJECTOR, idx);
        InjectorConfig source_cfg = new InjectorConfig();
        SingleSubnodeConfiguration tmp = loadSingleNodeConfigAndProperties(node_idx);
        if (tmp == null) {
            logger.warn(node_idx + " not configured");
        } else {
            source_cfg.setSourceConfig(tmp);
            source_cfg.setId(tmp.getId());
            source_cfg.setSourceClassName((String) tmp.getAttribute(ConfigConstants.CFGATTR_CLASSNAME));
        }

        return source_cfg;
    }

    protected EmitterConfig loadSinkConfig(int idx) {
        String node_idx = String.format(ConfigConstants.CFGKEY_FUNNEL_EMITTER, idx);

        EmitterConfig sink_cfg = new EmitterConfig();
        sink_cfg.setEmitterContainerClassName(ConfigConstants.DEFAULT_FUNNEL_EMITTERCONTAINER_CLASSNAME);

        MultiSubnodeConfiguration tmp = loadMutiNodeConfigAndProperties(node_idx);
        if (tmp == null) {
            logger.warn(node_idx + " not configured");
        } else {
            sink_cfg.setEmitterConfig(tmp);
            Map<String, String> classnames = getClassNames(tmp);
            sink_cfg.setEmitterClassNames(classnames);
        }

        return sink_cfg;
    }

    private Map<String, String> getClassNames(MultiSubnodeConfiguration clsConfig) {
        if (clsConfig == null)
            return null;

        Map<String, String> ans = new HashMap<String, String>(clsConfig.size());
        for (int i = 0; i < clsConfig.size(); i++) {
            Map<String, Object> m = clsConfig.get(i);
            ans.put((String) m.get(ConfigConstants.CFGATTR_ID), (String) m.get(ConfigConstants.CFGATTR_CLASSNAME));
        }

        return ans;
    }

    /**
     * Load configuration file and interpolate variables. Note that due to the
     * way Apache Commons Configuration treats property keys, user should avoid
     * using dot ('.') in the property key. Otherwise ACC may not substitute
     * some value if the variable contains valid element name(s).
     *
     * @param xmlConfigFile
     * @param propConfigFiles
     * @return
     * @throws ConfigurationException
     */
    protected HierarchicalConfiguration readConfigurationFiles(String xmlConfigFile, String propConfigFiles)
            throws ConfigurationException {
        try {
            // convert URI to URL
            URL[] prop_urls = null;
            URL xml_url = CommonUtils.uriToURL(xmlConfigFile);
            if (propConfigFiles != null) {
                String[] prop_files = propConfigFiles.split(",");
                prop_urls = new URL[prop_files.length];
                for (int i = 0; i < prop_files.length; i++) {
                    prop_urls[i] = CommonUtils.uriToURL(prop_files[i]);
                }
            }

            // combine xml and properties configurations
            CombinedConfiguration combined_cfg = new CombinedConfiguration(new OverrideCombiner());

            XMLConfiguration cfg_xml = new XMLConfiguration();
            cfg_xml.setDelimiterParsingDisabled(true);
            cfg_xml.setAttributeSplittingDisabled(true);
            cfg_xml.load(xml_url);

            combined_cfg.addConfiguration(cfg_xml);

            if (prop_urls != null) {
                // properties in the earlier files take precedence if duplicate
                for (int i = 0; i < prop_urls.length; i++) {
                    PropertiesConfiguration cfg_props = new PropertiesConfiguration();
                    cfg_props.setDelimiterParsingDisabled(true);
                    cfg_props.load(prop_urls[i]);

                    combined_cfg.addConfiguration(cfg_props);

                }
            }

            HierarchicalConfiguration config = (HierarchicalConfiguration) combined_cfg.interpolatedConfiguration(); // !!! resolve variables

            return config;
        } catch (Exception e) {
            throw new ConfigurationException(e.getMessage(), e);
        }

    }

    /**
     * Parse xml and build an config object. The returned object preserves the
     * order the elements appears in the xml files.
     *
     * @param key
     * @return
     */
    private MultiSubnodeConfiguration loadMutiNodeConfigAndProperties(String key) {

        logger.debug("------- looking up " + key + " -------");

        List<Map<String, Object>> list = XmlConfigUtil.parseMultiNodesAttributes(xmlConfig, key);
        if (list == null || list.size() == 0)
            return null;

        MultiSubnodeConfiguration c = new MultiSubnodeConfiguration();

        for (int i = 0; i < list.size(); i++) {
            SingleSubnodeConfiguration single = new SingleSubnodeConfiguration();
            Map<String, Object> member = list.get(i);
            single.putAll(member);
            single.setId((String) member.get(ConfigConstants.CFGATTR_ID));

            Map<String, PropertyValue> prop_map = getPropertyMap(
                    String.format(ConfigConstants.CFGKEY_PROPERTY_TEMPLATE, key, i));

            if (prop_map != null && prop_map.size() > 0) {
                // "properties" -> map of <name, value> pair
                single.setProperties(prop_map);
            }
            c.add(single);
        }

        return c;
    }

    private SingleSubnodeConfiguration loadSingleNodeConfigAndProperties(String key) {

        logger.debug("------- looking up " + key + " -------");

        Map<String, Object> member = XmlConfigUtil.parseSingleNodeAttributes(xmlConfig, key);
        if (member == null || member.size() == 0)
            return null;

        SingleSubnodeConfiguration single = new SingleSubnodeConfiguration();
        single.putAll(member);
        single.setId((String) member.get(ConfigConstants.CFGATTR_ID));

        Map<String, PropertyValue> prop_map = getPropertyMap(
                String.format(ConfigConstants.CFGKEY_PROPERTY_TEMPLATE, key, 0));

        if (prop_map != null && prop_map.size() > 0) {
            // "properties" -> map of <name, value> pair
            single.setProperties(prop_map);
        }

        return single;
    }

    private Map<String, PropertyValue> getPropertyMap(String key) {

        List<Map<String, Object>> list = XmlConfigUtil.parseMultiNodesAttributes(xmlConfig, key);

        if (list == null || list.size() == 0)
            return null;

        Map<String, PropertyValue> result = new HashMap<String, PropertyValue>();

        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> props = list.get(i);
            PropertyValue pv = new PropertyValue();
            String name = (String) props.get(ConfigConstants.CFGATTR_PROP_NAME);
            String value = (String) props.get(ConfigConstants.CFGATTR_PROP_VALUE);
            if (value != null) {
                pv.setName(name);
                pv.setValue(value);
                pv.setType(Type.IS_VALUE);

                String value_type = (String) props.get(ConfigConstants.CFGATTR_PROP_TYPE);
                if (value_type != null) {
                    DataType dtype = DataType.find(value_type);
                    if (dtype == null) {
                        String msg = "invalid value type" + value_type;
                        logger.error(msg);
                        throw new ConfigurationException(msg);
                    }

                    pv.setDataType(dtype);
                } else {
                    pv.setDataType(DataType.STRING); // default: string
                }

                String default_value = (String) props.get(ConfigConstants.CFGATTR_PROP_DEFAULT);
                if (default_value != null) {
                    pv.setDefaultValue(default_value);
                }

            } else {
                String ref = (String) props.get(ConfigConstants.CFGATTR_PROP_REF);
                if (ref != null) {
                    pv.setName(name);
                    pv.setValue(ref);
                    pv.setType(Type.IS_REF);
                }
            }

            result.put(name, pv);
        }

        return result;
    }

    private String lookupClassName(String nodeName) {
        SingleSubnodeConfiguration c = loadNodeConfig(nodeName);
        return (String) c.get(ConfigConstants.CFGATTR_CLASSNAME);
    }

    private SingleSubnodeConfiguration loadNodeConfig(String key) {

        logger.debug("------- looking up " + key + " -------");
        Map<String, Object> map = XmlConfigUtil.parseSingleNodeAttributes(xmlConfig, key);

        if (logger.isDebugEnabled()) {
            for (Map.Entry<String, Object> kv : map.entrySet()) {
                logger.debug(kv.getKey() + "=" + kv.getValue());
            }

        }

        SingleSubnodeConfiguration single = new SingleSubnodeConfiguration();
        single.putAll(map);
        single.setId((String) map.get(ConfigConstants.CFGATTR_ID));

        return single;
    }

    public void setConfigXmlFileUri(String configXmlFileUri) {
        this.configXmlFileUri = configXmlFileUri;
    }

    public void setConfigPropertyFiles(String configPropertyFiles) {
        this.configPropertyFiles = configPropertyFiles;
    }

    public void setSchemaLocationUri(String schemaLocationUri) {
        this.schemaLocationUri = schemaLocationUri;
    }

    public String getConfigXmlFileUri() {
        return configXmlFileUri;
    }

    public String getConfigPropertyFiles() {
        return configPropertyFiles;
    }

    public String getSchemaLocationUri() {
        return schemaLocationUri;
    }

    public QiaoConfig getQiaoConfig() {
        return qiaoConfig;
    }

}