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.Objects;
025import java.util.Properties;
026import java.util.logging.Level;
027import java.util.logging.Logger;
028
029/**
030 * Loader for the Java Money JSR configuration.
031 *
032 * @author Anatole Tresch
033 */
034public final class MonetaryConfig {
035
036    private static final Logger LOG = Logger
037            .getLogger(MonetaryConfig.class.getName());
038
039    private static final MonetaryConfig INSTANCE = new MonetaryConfig();
040
041    private final Map<String, String> config = new HashMap<>();
042    private final Map<String, Integer> priorities = new HashMap<>();
043
044    private MonetaryConfig() {
045        try {
046            Enumeration<URL> urls = getClass().getClassLoader().getResources(
047                    "javamoney.properties");
048            while (urls.hasMoreElements()) {
049                URL url = urls.nextElement();
050                try {
051                    Properties props = new Properties();
052                    props.load(url.openStream());
053                    updateConfig(props);
054                } catch (Exception e) {
055                    LOG.log(Level.SEVERE,
056                            "Error loading javamoney.properties, ignoring "
057                                    + url, e);
058                }
059            }
060        } catch (IOException e) {
061            LOG.log(Level.SEVERE, "Error loading javamoney.properties.", e);
062        }
063    }
064
065    private void updateConfig(Properties props) {
066        for (Map.Entry<Object, Object> en : props.entrySet()) {
067            String key = en.getKey().toString();
068            String value = en.getValue().toString();
069            int prio = 0;
070            if (key.startsWith("{")) {
071                int index = key.indexOf('}');
072                if (index > 0) {
073                    String prioString = key.substring(1, index);
074                    try {
075                        prio = Integer.parseInt(prioString);
076                        key = key.substring(index + 1);
077                    } catch (NumberFormatException e) {
078                        LOG.warning("Invalid config key in javamoney.properties: " + key);
079                    }
080                }
081            }
082            Integer existingPrio = priorities.get(key);
083            if (Objects.isNull(existingPrio)) {
084                priorities.put(key, prio);
085                config.put(key, value);
086            } else if (existingPrio < prio) {
087                priorities.put(key, prio);
088                config.put(key, value);
089            } else if (existingPrio == prio) {
090                throw new IllegalStateException(
091                        "AmbiguousConfiguration detected for '" + key + "'.");
092            }
093            // else ignore entry with lower prio!
094        }
095    }
096
097    public static Map<String, String> getConfig() {
098        return Collections.unmodifiableMap(INSTANCE.config);
099    }
100
101}