/* * Copyright 2014, The Sporting Exchange Limited * * 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.betfair.cougar.util.configuration; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.util.Collections; import java.util.Map; import java.util.Properties; import java.util.TreeMap; import org.jasypt.encryption.StringEncryptor; import org.jasypt.spring2.properties.EncryptablePropertyPlaceholderConfigurer; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import org.springframework.core.Ordered; import org.springframework.core.io.Resource; import org.springframework.util.DefaultPropertiesPersister; import org.springframework.util.PropertiesPersister; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PropertyConfigurer implements BeanFactoryAware, BeanNameAware, BeanFactoryPostProcessor, Ordered, InitializingBean { private static final Logger LOG = LoggerFactory.getLogger(PropertyConfigurer.class); public static final String NO_DEFAULT = "MUST_BE_OVERRIDDEN"; private static final String DEFAULT_CONFIG_HOST_PROPERTY = "betfair.config.host"; private static final String JMX_PORT_KEY = "jmx.html.port"; private static final String HOSTNAME_KEY = "system.hostname"; private static final String NODEID_KEY = "cougar.core.nodeid"; public static final String HOSTNAME; private static Map<String, String> allLoadedProperties = Collections.synchronizedMap(new TreeMap<String, String>()); private final PropertyPlaceholderConfigurer propertyPlaceholderConfigurer; private String configHostProp = DEFAULT_CONFIG_HOST_PROPERTY; private Resource defaultConfig; private String configOverride; static { try { HOSTNAME = InetAddress.getLocalHost().getHostName(); } catch (java.net.UnknownHostException e) { throw new IllegalArgumentException("Unable to generate name of local host", e); } } public PropertyConfigurer() { this((StringEncryptor)null); } public PropertyConfigurer(EncryptorRegistry registry) { this(registry.getEncryptor()); } protected PropertyConfigurer(StringEncryptor encryptor) { this.propertyPlaceholderConfigurer = encryptor != null ? new EncryptablePropertyPlaceholderConfigurer(encryptor) : new PropertyPlaceholderConfigurer(); // Ensure that system properties override the spring-set properties. propertyPlaceholderConfigurer.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE); PropertiesPersister savingPropertiesPersister = new DefaultPropertiesPersister() { @Override public void load(Properties props, InputStream is) throws IOException { props.put(HOSTNAME_KEY, HOSTNAME); CougarNodeId.initialiseNodeId(props); super.load(props, is); for (String propName: props.stringPropertyNames()) { allLoadedProperties.put(propName, System.getProperty(propName, props.getProperty(propName))); } }}; propertyPlaceholderConfigurer.setPropertiesPersister(savingPropertiesPersister); } public static Map<String, String> getAllLoadedProperties() { return allLoadedProperties; } public void setPlaceholderPrefix(String placeholderPrefix) { this.propertyPlaceholderConfigurer.setPlaceholderPrefix(placeholderPrefix); } public void setConfigHost(String configHost) { this.configHostProp = configHost; } public void setDefaultConfig(Resource defaultConfig) { this.defaultConfig = defaultConfig; } public void setConfigOverride(String configOverride) { this.configOverride = configOverride; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { propertyPlaceholderConfigurer.setBeanFactory(beanFactory); } @Override public void setBeanName(String beanName) { propertyPlaceholderConfigurer.setBeanName(beanName); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException { propertyPlaceholderConfigurer.postProcessBeanFactory(arg0); } @Override public int getOrder() { return propertyPlaceholderConfigurer.getOrder(); } @Override public void afterPropertiesSet() throws Exception { PropertyLoader pl = new PropertyLoader(defaultConfig, configOverride, LOG); propertyPlaceholderConfigurer.setLocations(pl.constructResourceList()); } // Inner class containing the logic for defining the cougar.core.nodeId property public static class CougarNodeId{ // Create a unique node id for the service by combining the host name and jmx port // If no jmx port is defined then leave the node id property undefined public static void initialiseNodeId(Properties props){ if(props.containsKey(JMX_PORT_KEY) && !("-1").equals(props.get(JMX_PORT_KEY))){ props.put(NODEID_KEY, (String)props.get(HOSTNAME_KEY)+props.get(JMX_PORT_KEY)); } } } }