/* * Copyright (c) 2012-2015, Luigi R. Viggiano * All rights reserved. * * This software is distributable under the BSD license. * See the terms of the BSD license in the documentation provided with this software. */ package org.aeonbits.owner; import org.aeonbits.owner.loaders.Loader; import javax.management.DynamicMBean; import java.util.Map; import java.util.Properties; import java.util.concurrent.ScheduledExecutorService; import static java.lang.reflect.Proxy.newProxyInstance; import static org.aeonbits.owner.util.Reflection.isClassAvailable; /** * Default implementation for {@link Factory}. * * @author Luigi R. Viggiano */ class DefaultFactory implements Factory { private static final boolean isJMXAvailable = isClassAvailable("javax.management.DynamicMBean"); private final ScheduledExecutorService scheduler; private Properties props; final LoadersManager loadersManager; DefaultFactory(ScheduledExecutorService scheduler, Properties props) { this.scheduler = scheduler; this.props = props; this.loadersManager = new LoadersManager(); } @SuppressWarnings("unchecked") public <T extends Config> T create(Class<? extends T> clazz, Map<?, ?>... imports) { Class<?>[] interfaces = interfaces(clazz); VariablesExpander expander = new VariablesExpander(props); PropertiesManager manager = new PropertiesManager(clazz, new Properties(), scheduler, expander, loadersManager, imports); Object jmxSupport = getJMXSupport(clazz, manager); PropertiesInvocationHandler handler = new PropertiesInvocationHandler(manager, jmxSupport); T proxy = (T) newProxyInstance(clazz.getClassLoader(), interfaces, handler); handler.setProxy(proxy); return proxy; } public String setProperty(String key, String value) { checkKey(key); return (String) props.setProperty(key, value); } private void checkKey(String key) { if (key == null) throw new IllegalArgumentException("key can't be null"); if (key.isEmpty()) throw new IllegalArgumentException("key can't be empty"); } public Properties getProperties() { return props; } public void setProperties(Properties properties) { if (properties == null) props = new Properties(); else props = properties; } public void registerLoader(Loader loader) { loadersManager.registerLoader(loader); } public void setTypeConverter(Class<?> type, Class<? extends Converter<?>> converter) { Converters.setTypeConverter(type, converter); } public void removeTypeConverter(Class<?> type){ Converters.removeTypeConverter(type); } public String getProperty(String key) { checkKey(key); return props.getProperty(key); } public String clearProperty(String key) { checkKey(key); return (String) props.remove(key); } private Object getJMXSupport(Class<?> clazz, PropertiesManager manager) { if (isJMXAvailable) return new JMXSupport(clazz, manager); return null; } private <T extends Config> Class<?>[] interfaces(Class<? extends T> clazz) { if (isJMXAvailable) return new Class<?>[]{clazz, DynamicMBean.class}; else return new Class<?>[]{clazz}; } }