001/**
002 * Copyright (c) 2012, 2014, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016package org.javamoney.moneta.spi;
017
018import java.io.IOException;
019import java.net.URL;
020import java.util.Collections;
021import java.util.Enumeration;
022import java.util.HashMap;
023import java.util.Map;
024import java.util.Properties;
025import java.util.logging.Level;
026import java.util.logging.Logger;
027
028/**
029 * Loader for the Java Money JSR configuration.
030 *
031 * @author Anatole Tresch
032 */
033public final class MonetaryConfig {
034
035    private static final Logger LOG = Logger
036            .getLogger(MonetaryConfig.class.getName());
037
038    private static final MonetaryConfig INSTANCE = new MonetaryConfig();
039
040    private final Map<String, String> config = new HashMap<>();
041    private final Map<String, Integer> priorities = new HashMap<>();
042
043    private MonetaryConfig() {
044        try {
045            Enumeration<URL> urls = getClass().getClassLoader().getResources(
046                    "javamoney.properties");
047            while (urls.hasMoreElements()) {
048                URL url = urls.nextElement();
049                try {
050                    Properties props = new Properties();
051                    props.load(url.openStream());
052                    updateConfig(props);
053                } catch (Exception e) {
054                    LOG.log(Level.SEVERE,
055                            "Error loading javamoney.properties, ignoring "
056                                    + url, e);
057                }
058            }
059        } catch (IOException e) {
060            LOG.log(Level.SEVERE, "Error loading javamoney.properties.", e);
061        }
062    }
063
064    private void updateConfig(Properties props) {
065        for (Map.Entry<Object, Object> en : props.entrySet()) {
066            String key = en.getKey().toString();
067            String value = en.getValue().toString();
068            int prio = 0;
069            if (key.startsWith("{")) {
070                int index = key.indexOf('}');
071                if (index > 0) {
072                    String prioString = key.substring(1, index);
073                    try {
074                        prio = Integer.parseInt(prioString);
075                        key = key.substring(index + 1);
076                    } catch (NumberFormatException e) {
077                        LOG.warning("Invalid config key in javamoney.properties: " + key);
078                    }
079                }
080            }
081            Integer existingPrio = priorities.get(key);
082            if (existingPrio==null) {
083                priorities.put(key, prio);
084                config.put(key, value);
085            } else if (existingPrio < prio) {
086                priorities.put(key, prio);
087                config.put(key, value);
088            } else if (existingPrio == prio) {
089                String oldValue = props.getProperty(key);
090                if(!value.equals(oldValue)){
091                    throw new IllegalStateException(
092                            "AmbiguousConfiguration detected for '" + key + "'.");
093                }
094            }
095            // else ignore entry with lower prio!
096        }
097    }
098
099    public static Map<String, String> getConfig() {
100        return Collections.unmodifiableMap(INSTANCE.config);
101    }
102
103}