org.cloudfoundry.reconfiguration.util.StandardPropertyAugmenter.java Source code

Java tutorial

Introduction

Here is the source code for org.cloudfoundry.reconfiguration.util.StandardPropertyAugmenter.java

Source

/*
 * Copyright 2011-2014 the original author or authors.
 *
 * 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 org.cloudfoundry.reconfiguration.util;

import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.ManagedProperties;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import java.io.IOException;
import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * Standard implementation of {@link PropertyAugmenter}
 */
public final class StandardPropertyAugmenter implements PropertyAugmenter {

    @Override
    public void augment(ConfigurableListableBeanFactory beanFactory, Class<?> beanClass, String key,
            ManagedProperties additionalProperties) {
        additionalProperties.setMergeEnabled(true);

        for (String beanName : beanFactory.getBeanNamesForType(beanClass, true, false)) {
            MutablePropertyValues propertyValues = getBeanDefinition(beanFactory, beanName).getPropertyValues();
            Properties originalValue = extractOriginalValue(beanFactory, propertyValues.getPropertyValue(key));

            propertyValues.addPropertyValue(key, additionalProperties.merge(originalValue));
        }
    }

    private Properties extractOriginalValue(ConfigurableListableBeanFactory beanFactory,
            PropertyValue originalProperty) {
        if (originalProperty == null) {
            return new ManagedProperties();
        }

        Object value = originalProperty.getValue();
        if (value instanceof Properties) {
            return (Properties) value;
        } else if (value instanceof BeanDefinitionHolder) {
            return extractProperties((BeanDefinitionHolder) value);
        } else if (value instanceof BeanReference) {
            return extractProperties((BeanReference) value, beanFactory);
        } else if (value instanceof TypedStringValue) {
            return extractProperties((TypedStringValue) value);
        }

        throw new IllegalStateException(String.format("Unable to process property '%s' of type %s",
                originalProperty.getName(), value.getClass().getName()));
    }

    private BeanDefinition getBeanDefinition(ConfigurableListableBeanFactory beanFactory, String beanName) {
        String canonicalBeanName;
        if (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
            canonicalBeanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        } else {
            canonicalBeanName = beanName;
        }

        return beanFactory.getBeanDefinition(canonicalBeanName);
    }

    private Properties extractProperties(BeanDefinitionHolder beanDefinitionHolder) {
        BeanDefinition beanDefinition = beanDefinitionHolder.getBeanDefinition();
        return getMapWrappingBeanProperties(beanDefinition);
    }

    private Properties extractProperties(BeanReference beanReference, ConfigurableListableBeanFactory beanFactory) {
        BeanDefinition beanDefinition = getBeanDefinition(beanFactory, beanReference.getBeanName());
        return getMapWrappingBeanProperties(beanDefinition);
    }

    private Properties extractProperties(TypedStringValue value) {
        try {
            Properties properties = new Properties();
            properties.load(new StringReader(value.getValue()));
            return properties;
        } catch (IOException e) {
            throw new IllegalStateException(String.format("Error loading properties from '%s'", value), e);
        }
    }

    @SuppressWarnings("unchecked")
    private Properties getMapWrappingBeanProperties(BeanDefinition beanDefinition) {
        if (beanDefinition.getBeanClassName().equals(PropertiesFactoryBean.class.getName())) {
            return getPropertiesFactoryBeanProperties(beanDefinition);
        } else {
            return convert((Map<String, String>) beanDefinition.getPropertyValues().getPropertyValue("sourceMap")
                    .getValue());
        }
    }

    @SuppressWarnings("unchecked")
    private Properties getPropertiesFactoryBeanProperties(BeanDefinition beanDefinition) {
        PropertyValues propertyValues = beanDefinition.getPropertyValues();
        if (propertyValues.contains("location")) {
            return loadPropertiesForLocation(propertyValues.getPropertyValue("location").getValue());
        } else if (propertyValues.contains("locations")) {
            return loadPropertiesForLocations(propertyValues.getPropertyValue("locations").getValue());
        } else if (propertyValues.contains("properties")) {
            Object value = propertyValues.getPropertyValue("properties").getValue();
            if (value instanceof BeanDefinitionHolder) {
                return extractProperties((BeanDefinitionHolder) value);
            } else {
                return convert((Map<String, String>) value);
            }
        }

        throw new IllegalArgumentException(
                "Unable to process PropertiesFactoryBean; doesn't contain either 'locations' or 'properties' property");
    }

    private Properties loadPropertiesForLocation(Object location) {
        try {
            if (location instanceof String) {
                return PropertiesLoaderUtils.loadAllProperties((String) location);
            } else if (location instanceof TypedStringValue) {
                return PropertiesLoaderUtils.loadAllProperties(((TypedStringValue) location).getValue());
            }
        } catch (IOException e) {
            throw new IllegalArgumentException(String.format("Unable to load properties from '%s'", location), e);
        }

        throw new IllegalArgumentException(
                String.format("Unable to process 'location' value of type %s", location.getClass().getName()));
    }

    private Properties loadPropertiesForLocations(Object locations) {
        List normalizedLocations;

        if (locations instanceof Object[]) {
            normalizedLocations = Arrays.asList((Object[]) locations);
        } else if (locations instanceof List) {
            normalizedLocations = (List) locations;
        } else {
            throw new IllegalArgumentException(String.format("Unable to process 'locations' value of type %s",
                    locations.getClass().getName()));
        }

        Properties props = new Properties();
        for (Object location : normalizedLocations) {
            props.putAll(loadPropertiesForLocation(location));
        }

        return props;
    }

    private Properties convert(Map<String, String> map) {
        Properties properties = new Properties();
        properties.putAll(map);
        return properties;
    }

}