001package com.randomnoun.common;
002
003/* (c) 2013 randomnoun. All Rights Reserved. This work is licensed under a
004 * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html)
005 */
006
007import java.io.File;
008import java.io.InputStream;
009import java.io.FileInputStream;
010import java.io.IOException;
011import java.io.LineNumberReader;
012import java.io.InputStreamReader;
013import java.text.ParseException;
014
015import java.util.HashMap;
016import java.util.Map;
017import java.util.Set;
018
019
020/** Windows .ini file parser
021 * 
022 * Properties without explicit groups are recorded with a null group
023 * 
024 * 
025 */
026public class IniFile {
027    
028    
029
030
031        /** Map of property groups to property name-value pairs */
032        private Map<String, Map<String, String>> properties;
033        
034        public IniFile() {
035                properties = new HashMap<String, Map<String, String>>();
036        
037        }
038        
039        public void load(File file) throws IOException, ParseException {
040                InputStream is = new FileInputStream(file);
041                load(is);
042        }
043        
044        public void load(InputStream is) throws IOException, ParseException {
045                LineNumberReader lnr = new LineNumberReader(new InputStreamReader(is));
046                try {
047                        String line = lnr.readLine();
048                        String group = null;
049                        while(line!=null) {
050                                // @TODO handle newlines 
051                                line = line.trim();
052                                if (line.startsWith(";")) {
053                                        // comment; ignore
054                                } else if (line.startsWith("[")) {
055                                        if (line.endsWith("]")) {
056                                                group = line.substring(1, line.length()-1);
057                                        } else {
058                                                throw new ParseException("Line " + lnr.getLineNumber() + ": invalid .ini group declaration", 0);
059                                        }
060                                } else if (line.contains("=")) {
061                                        int pos = line.indexOf("=");
062                                        String name = line.substring(0, pos);
063                                        String value = line.substring(pos+1);
064                                        Map<String, String> propMap = properties.get(group);
065                                        if (propMap==null) {
066                                                propMap = new HashMap<String, String>();
067                                                properties.put(group, propMap);
068                                        }
069                                        propMap.put(name, value);
070                                }
071                                
072                                line=lnr.readLine();
073                        }
074                } finally {
075                        try {
076                                is.close();     
077                        } catch (IOException ioe) {
078                                // ignore
079                        }
080                }
081        }
082        
083        public String get(String group, String key) {
084                Map<String, String> propMap = properties.get(group);
085                if (propMap==null) { return null; }
086                return propMap.get(key);
087        }
088        
089        public Set<String> getGroups() {
090                return properties.keySet();
091        }
092        
093        public Set<String> getGroupKeys(String group) {
094                Map<String, String> propMap = properties.get(group);
095                if (propMap==null) { return null; }
096                return propMap.keySet();
097        }
098        
099}