Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 de.extra.client.core.annotation; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Properties; import org.apache.commons.lang.StringUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import org.springframework.util.Assert; import de.extra.client.core.builder.IXmlComplexTypeBuilder; /** * <pre> * This class extends the PropertyPlaceholderConfigurer so that we will able to * configure our plugins. * This code is taken and extended from: * http://stackoverflow.com/questions/317687/inject-property-value-into-spring-bean * </pre> * * @author Leonid Potap * @version 1.0.0 * @since 1.0.0 */ public class PropertyPlaceholderPluginConfigurer extends PropertyPlaceholderConfigurer { private static final Logger LOG = LoggerFactory.getLogger(PropertyPlaceholderPluginConfigurer.class); private static final String VALUE_SEPARATOR = ":"; private boolean ignoreNullValues = false; private final StringEncryptor stringEncryptor; public PropertyPlaceholderPluginConfigurer(final StringEncryptor stringEncryptor) { Assert.notNull(stringEncryptor); this.stringEncryptor = stringEncryptor; } @Override protected void processProperties(final ConfigurableListableBeanFactory beanFactory, final Properties properties) throws BeansException { super.processProperties(beanFactory, properties); for (final String beanName : beanFactory.getBeanDefinitionNames()) { final Class<?> clazz = beanFactory.getType(beanName); if (LOG.isDebugEnabled()) { LOG.debug("Configuring properties for bean=" + beanName + "[" + clazz + "]"); } if (clazz != null && clazz.isAnnotationPresent(PluginConfiguration.class)) { setPluginProperties(beanFactory, properties, beanName, clazz); } } } private void setPluginProperties(final ConfigurableListableBeanFactory beanFactory, final Properties properties, final String beanName, final Class<?> clazz) { final PluginConfiguration annotationConfigutation = clazz.getAnnotation(PluginConfiguration.class); final MutablePropertyValues mutablePropertyValues = beanFactory.getBeanDefinition(beanName) .getPropertyValues(); for (final PropertyDescriptor property : BeanUtils.getPropertyDescriptors(clazz)) { final Method setter = property.getWriteMethod(); PluginValue valueAnnotation = null; if (setter != null && setter.isAnnotationPresent(PluginValue.class)) { valueAnnotation = setter.getAnnotation(PluginValue.class); } if (valueAnnotation != null) { final String key = extractKey(annotationConfigutation, valueAnnotation, clazz); final String value = resolvePlaceholder(key, properties, SYSTEM_PROPERTIES_MODE_FALLBACK); if (StringUtils.isEmpty(value)) { throw new BeanCreationException(beanName, "No such property=[" + key + "] found in properties."); } if (LOG.isDebugEnabled()) { LOG.debug("setting property=[" + clazz.getName() + "." + property.getName() + "] value=[" + key + "=" + value + "]"); } mutablePropertyValues.addPropertyValue(property.getName(), value); } } for (final Field field : clazz.getDeclaredFields()) { if (LOG.isDebugEnabled()) { LOG.debug("examining field=[" + clazz.getName() + "." + field.getName() + "]"); } if (field.isAnnotationPresent(PluginValue.class)) { final PluginValue valueAnnotation = field.getAnnotation(PluginValue.class); final PropertyDescriptor property = BeanUtils.getPropertyDescriptor(clazz, field.getName()); if (property == null || property.getWriteMethod() == null) { throw new BeanCreationException(beanName, "setter for property=[" + clazz.getName() + "." + field.getName() + "] not available."); } final String key = extractKey(annotationConfigutation, valueAnnotation, clazz); String value = resolvePlaceholder(key, properties, SYSTEM_PROPERTIES_MODE_FALLBACK); if (value == null) { // DEFAULT Value suchen final int separatorIndex = key.indexOf(VALUE_SEPARATOR); if (separatorIndex != -1) { final String actualPlaceholder = key.substring(0, separatorIndex); final String defaultValue = key.substring(separatorIndex + VALUE_SEPARATOR.length()); value = resolvePlaceholder(actualPlaceholder, properties, SYSTEM_PROPERTIES_MODE_FALLBACK); if (value == null) { value = defaultValue; } } } if (value != null) { if (LOG.isDebugEnabled()) { LOG.debug("setting property=[" + clazz.getName() + "." + field.getName() + "] value=[" + key + "=" + value + "]"); } mutablePropertyValues.addPropertyValue(field.getName(), value); } else if (!ignoreNullValues) { throw new BeanCreationException(beanName, "No such property=[" + key + "] found in properties."); } } } } /** * Entschlsselt evtl. verschlsselte Werte. * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } return PropertyValueEncryptionUtils.decrypt(originalValue, stringEncryptor); } /** * @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#resolveSystemProperty(java.lang.String) */ @Override protected String resolveSystemProperty(final String key) { return convertPropertyValue(super.resolveSystemProperty(key)); } /** * Findet Key Anhang Annotation. * * @param annotation * @return */ private String extractKey(final PluginConfiguration annotation, final PluginValue value, final Class<?> clazz) { try { final String initialKey = value.key(); final String plugInBeanName = annotation.pluginBeanName(); final PluginConfigType pluginConfigType = annotation.pluginType(); final StringBuilder key = new StringBuilder(); final String configPrefix = annotation.pluginType().getConfigPrefix(); if (PluginConfigType.Builder == pluginConfigType) { key.append(configPrefix); final Object bean = clazz.newInstance(); if (bean instanceof IXmlComplexTypeBuilder) { final IXmlComplexTypeBuilder iXmlComplexTypeBuilder = (IXmlComplexTypeBuilder) bean; final String xmlType = iXmlComplexTypeBuilder.getXmlType(); final String xmlTypeKey = extractKeyFromXmlType(xmlType); key.append(".").append(xmlTypeKey); key.append(".").append(plugInBeanName); key.append(".").append(initialKey); } else { throw new BeanCreationException(clazz.getName(), " unexpected AnnotationType. Use PluginConfigType.Builder for IXmlComplexTypeBuilder"); } } else { key.append(configPrefix).append(".").append(plugInBeanName).append(".").append(initialKey); } return key.toString(); } catch (final IllegalAccessException illegalAccessException) { throw new BeanCreationException("IllegalAccessException", illegalAccessException); } catch (final InstantiationException instantiationException) { throw new BeanCreationException("InstantiationException", instantiationException); } } /** * Berechnet Key aus dem xmlType indem ':' durch '.' replased wird * * @param xmlType * @return */ private String extractKeyFromXmlType(final String xmlType) { final String xmlTypeKey = StringUtils.replace(xmlType, ":", "."); return xmlTypeKey; } /** * @param ignoreNullValues * the ignoreNullValues to set */ public void setIgnoreNullValues(final boolean ignoreNullValues) { this.ignoreNullValues = ignoreNullValues; } }