Package com.linkedin.databus.core.util

Source Code of com.linkedin.databus.core.util.ConfigLoader

package com.linkedin.databus.core.util;
/*
*
* Copyright 2013 LinkedIn Corp. All rights reserved
*
* 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.
*
*/


import java.beans.PropertyDescriptor;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;


/**
* A helper class for loading configurations from property files and JSON
* @author cbotev
*
* @param <D>   Config class
*/
public class ConfigLoader<D> extends ReadWriteSyncedObject
{
  public final static String MODULE = ConfigLoader.class.getName();
  public final static Logger LOG = Logger.getLogger(MODULE);

  protected final String _propPrefix;
  protected final ConfigBuilder<D> _configBuilder;
  private BeanUtilsBean _beanUtilsBean;

  public ConfigLoader(String propPrefix, ConfigBuilder<D> dynConfigBuilder)
                    throws InvalidConfigException
  {
  super(true);
  _propPrefix = propPrefix;
  _configBuilder = dynConfigBuilder;
  _beanUtilsBean = new BeanUtilsBean();
  }

  public D loadConfig(Map<?, ?> props) throws InvalidConfigException
  {
  Map<String, Object> realProps = new HashMap<String, Object>();
  D result = null;
  if (_propPrefix != null && _propPrefix.length() > 0)
  {
      int prefixLen = _propPrefix.length();
    for (Map.Entry<?, ?> entry: props.entrySet())
    {
      String keyStr = entry.getKey().toString();
      if (keyStr.startsWith(_propPrefix))
      {
        String realKey = keyStr.substring(prefixLen);
        realProps.put(realKey, entry.getValue());
      }
    }
  }
  else
  {
      for (Map.Entry<?, ?> entry: props.entrySet())
      {
        realProps.put(entry.getKey().toString(), entry.getValue());
      }
  }

  synchronized (_configBuilder)
  {
      for (Map.Entry<String, Object> entry : realProps.entrySet())
    {
      setBareSetting(entry.getKey(), entry.getValue());
    }

       result = _configBuilder.build();
  }

  return result;
  }

  private void setBareSetting(String settingName, Object value) throws InvalidConfigException
  {
    //check syntax because beanutils silently ignore settings with typos
    PropertyDescriptor propDesc = null;
    try
    {
       propDesc = _beanUtilsBean.getPropertyUtils().getPropertyDescriptor(_configBuilder, settingName);
    }
    catch (Exception e)
    {
      throw new InvalidConfigException("Error obtaining configuration property. settingName=" + settingName, e);
    }
    if (null == propDesc)
    {
      throw new InvalidConfigException("Unknown configuration property:" + settingName);
    }

    try
    {
      if (value instanceof String)
      {
        value = ((String)value).trim();
      }

      _beanUtilsBean.setProperty(_configBuilder, settingName, value);
    }
    catch (Exception e)
    {
      throw new InvalidConfigException("setting failed: " + settingName, e);
    }
  }

  public D setSetting(String settingName, Object value) throws InvalidConfigException
  {
    synchronized (_configBuilder)
    {
      if (settingName.startsWith(_propPrefix))
      {
        String realKey = settingName.substring(_propPrefix.length());
        setBareSetting(realKey, value);
      }

      D newConfig = _configBuilder.build();
      return newConfig;
    }
  }

  public D loadConfigFromJson(Reader jsonReader) throws InvalidConfigException
  {
    D newConfig = null;
  try
  {
    ObjectMapper _jsonMapper = new ObjectMapper();
    Map<?, ?> jsonMap = _jsonMapper.readValue(jsonReader, new TypeReference<Map<?, ?>>(){});
    synchronized (_configBuilder)
      {
        fillBeanFromMap(_configBuilder, jsonMap);
      }

    newConfig = _configBuilder.build();
    }
    catch (Exception e)
  {
    throw new InvalidConfigException("Load from JSON failed", e);
  }

    return newConfig;
  }

  private void fillBeanFromMap(Object bean, Map<?, ?> map) throws IllegalAccessException,
                                                                  InvocationTargetException,
                                                                  NoSuchMethodException
  {
      PropertyUtilsBean propUtils = _beanUtilsBean.getPropertyUtils();

      for (Map.Entry<?, ?> entry : map.entrySet())
    {
      String keyStr = entry.getKey().toString();
      Object value = entry.getValue();
      if (value instanceof Map<?, ?>)
      {
        Object subBean = propUtils.getProperty(bean, keyStr);
        if (null != subBean) fillBeanFromMap(subBean, (Map<?, ?>)value);
      }
      else if (value instanceof List<?>)
      {
        fillPropertyFromList(bean, keyStr, (List<?>)value);
      }
      else
      {
        propUtils.setProperty(bean, keyStr, value);
      }
    }
  }

  private void fillPropertyFromList(Object bean, String propName, List<?> values)
                                    throws IllegalAccessException,
                                             InvocationTargetException,
                                             NoSuchMethodException
  {
      PropertyUtilsBean propUtils = _beanUtilsBean.getPropertyUtils();
      int idx = 0;
      for (Object elem: values)
      {
        if (elem instanceof Map<?,?>)
        {
          Object subBean = propUtils.getIndexedProperty(bean, propName, idx);
          fillBeanFromMap(subBean, (Map<?, ?>)elem);
        }
        else
        {
          propUtils.setIndexedProperty(bean, propName, idx, elem);
        }
        ++idx;
      }
  }

  /**
   * Provides direct access to the config builder.
   */
  public ConfigBuilder<D> getConfigBuilder()
  {
    return _configBuilder;
  }

  public String getPropPrefix()
  {
    return _propPrefix;
  }

}
TOP

Related Classes of com.linkedin.databus.core.util.ConfigLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.