/* * HA-JDBC: High-Availability JDBC * Copyright (C) 2014 Paul Ferraro * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.hajdbc.configuration; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.beans.PropertyEditor; import java.beans.PropertyEditorManager; import java.lang.reflect.InvocationTargetException; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.HashMap; import java.util.Map; import net.sf.hajdbc.Identifiable; import net.sf.hajdbc.messages.Messages; import net.sf.hajdbc.messages.MessagesFactory; public class ServiceBuilder<T extends Identifiable> extends SimpleServiceBuilder<T> implements PropertiesBuilder<T> { private static final Messages messages = MessagesFactory.getMessages(); private final Map<String, String> properties = new HashMap<>(); public ServiceBuilder(Class<T> serviceClass, String id) { super(serviceClass, id); } @Override public ServiceBuilder<T> property(String name, String value) { this.properties.put(name, value); return this; } @Override public ServiceBuilder<T> read(T service) { super.read(service); for (Map.Entry<String, Map.Entry<PropertyDescriptor, PropertyEditor>> entry: findDescriptors(service.getClass()).entrySet()) { Map.Entry<PropertyDescriptor, PropertyEditor> descriptorEntry = entry.getValue(); PropertyDescriptor descriptor = descriptorEntry.getKey(); PropertyEditor editor = descriptorEntry.getValue(); try { Object value = descriptor.getReadMethod().invoke(service); editor.setValue(value); this.properties.put(entry.getKey(), editor.getAsText()); } catch (IllegalAccessException e) { throw new IllegalStateException(e); } catch (InvocationTargetException e) { throw new IllegalStateException(e.getTargetException()); } } return this; } @Override public T build() { T service = super.build(); if (!this.properties.isEmpty()) { Map<String, Map.Entry<PropertyDescriptor, PropertyEditor>> descriptors = findDescriptors(service.getClass()); for (Map.Entry<String, String> property: this.properties.entrySet()) { String name = property.getKey(); String value = property.getValue(); Map.Entry<PropertyDescriptor, PropertyEditor> entry = descriptors.get(name); if (entry == null) { throw new IllegalArgumentException(messages.invalidJavaBeanProperty(service.getClass(), name)); } PropertyDescriptor descriptor = entry.getKey(); PropertyEditor editor = entry.getValue(); try { editor.setAsText(value); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(messages.invalidJavaBeanPropertyValue(descriptor, value), e); } try { descriptor.getWriteMethod().invoke(service, editor.getValue()); } catch (IllegalAccessException e) { throw new IllegalStateException(e); } catch (InvocationTargetException e) { throw new IllegalStateException(e.getTargetException()); } } } return service; } static Map<String, Map.Entry<PropertyDescriptor, PropertyEditor>> findDescriptors(Class<?> targetClass) { Map<String, Map.Entry<PropertyDescriptor, PropertyEditor>> map = new HashMap<>(); try { for (PropertyDescriptor descriptor: Introspector.getBeanInfo(targetClass).getPropertyDescriptors()) { if ((descriptor.getReadMethod() != null) && (descriptor.getWriteMethod() != null)) { PropertyEditor editor = PropertyEditorManager.findEditor(descriptor.getPropertyType()); if (editor != null) { map.put(descriptor.getName(), new SimpleImmutableEntry<>(descriptor, editor)); } } } return map; } catch (IntrospectionException e) { throw new IllegalStateException(e); } } }