001    package railo.commons.io.ini;
002    
003    import java.io.BufferedReader;
004    import java.io.IOException;
005    import java.io.InputStream;
006    import java.io.InputStreamReader;
007    import java.io.OutputStream;
008    import java.io.PrintWriter;
009    import java.util.Iterator;
010    import java.util.LinkedHashMap;
011    import java.util.Map;
012    
013    import railo.commons.io.IOUtil;
014    import railo.commons.io.res.Resource;
015    import railo.runtime.type.Struct;
016    import railo.runtime.type.StructImpl;
017    
018    /**
019    * read a ini file and allow to modifie and read the data
020    */
021    public final class IniFile {
022    
023            private Map sections;
024            private final Resource file;
025     
026            private static Map newMap() {return new LinkedHashMap();}
027     
028     /**
029      * Constructor for the IniFile object
030      *
031      * @param file ini FIle
032     * @throws IOException
033      */
034             public IniFile(Resource file) throws IOException {
035                 this.file=file;
036                 sections = newMap();
037                 InputStream is=null;
038                 if(!file.exists())file.createFile(false);
039                 try {
040                     load(is=file.getInputStream());
041                 }
042                 finally {
043                     IOUtil.closeEL(is);
044                 }
045             }
046             
047             public IniFile(InputStream is) throws IOException {
048                 sections = newMap();
049                 load(is);
050                 file=null;
051             }
052    
053     /**
054      * Sets the KeyValue attribute of the IniFile object
055      *
056      * @param strSection  the section to set
057      * @param key the key of the new value
058      * @param value the value to set
059      */
060     public void setKeyValue(String strSection, String key, String value) {
061         Map section = getSectionEL(strSection);
062         if(section==null) {
063             section=newMap();
064             sections.put(strSection.toLowerCase(),section);
065         }
066         section.put(key.toLowerCase(), value);
067     }
068    
069     /**
070      * Gets the Sections attribute of the IniFile object
071      *
072      * @return   The Sections value
073      */
074     public Map getSections() {
075       return sections;
076     }
077    
078     /**
079      * Gets the Section attribute of the IniFile object
080      *
081      * @param strSection  section name to get
082      * @return         The Section value
083     * @throws IOException
084      */
085     public Map getSection(String strSection) throws IOException {
086         Object o=sections.get(strSection.toLowerCase());
087         if(o==null) throw new IOException("section with name "+strSection+" does not exist");
088         return (Map) o;
089       }
090     /**
091      * Gets the Section attribute of the IniFile object, return null if section not exist
092      *
093      * @param strSection  section name to get
094      * @return         The Section value
095      */
096     public Map getSectionEL(String strSection) {
097         Object o=sections.get(strSection.toLowerCase());
098         if(o==null) return null;
099         return (Map) o;
100       }
101    
102     /**
103      * Gets the NullOrEmpty attribute of the IniFile object
104      *
105      * @param section  section to check
106      * @param key      key to check
107      * @return         is empty or not
108      */
109     public boolean isNullOrEmpty(String section, String key) {
110       String value = getKeyValueEL(section, key);
111       return (value == null || value.length() == 0);
112     }
113    
114     /**
115      * Gets the KeyValue attribute of the IniFile object
116      *
117      * @param strSection  section to get
118      * @param key      key to get
119      * @return         matching alue
120     * @throws IOException
121      */
122     public String getKeyValue(String strSection, String key) throws IOException {
123         Object o= getSection(strSection).get(key.toLowerCase());
124         if(o==null) throw new IOException("key "+key+" doesn't exist in section "+strSection);
125         return (String)o;
126    
127     }
128     /**
129      * Gets the KeyValue attribute of the IniFile object, if not exists return null
130      *
131      * @param strSection  section to get
132      * @param key      key to get
133      * @return         matching alue
134      */
135     public String getKeyValueEL(String strSection, String key) {
136         Map map=getSectionEL(strSection);
137         if(map==null) return null;
138         Object o=map.get(key.toLowerCase());
139         if(o==null) return null;
140         return (String) o;
141    
142     }
143    
144    
145     /**
146      * loads the ini file
147      * @param in  inputstream to read
148     * @throws IOException
149      */
150     public void load(InputStream in) throws IOException {
151       
152         BufferedReader input = IOUtil.toBufferedReader(new InputStreamReader(in));
153         String read;
154         Map section = null;
155         String sectionName;
156         while ((read = input.readLine()) != null) {
157           if (read.startsWith(";") || read.startsWith("#")) {
158             continue;
159           }
160           else if (read.startsWith("[")) {
161             // new section
162             sectionName = read.substring(1, read.indexOf("]")).trim().toLowerCase();
163             section = getSectionEL(sectionName);
164             if (section == null) {
165               section = newMap();
166               sections.put(sectionName, section);
167             }
168           }
169           else if (read.indexOf("=") != -1 && section != null) {
170             // new key
171             String key = read.substring(0, read.indexOf("=")).trim().toLowerCase();
172             String value = read.substring(read.indexOf("=") + 1).trim();
173             if(section!=null)section.put(key, value);
174           }
175         }
176    
177     }
178    
179     /**
180      * save back content to ini file
181      * @throws IOException
182      */
183     public void save() throws IOException {
184             if(!file.exists())file.createFile(true);
185         OutputStream out=IOUtil.toBufferedOutputStream(file.getOutputStream());
186         Iterator it = sections.keySet().iterator();
187         PrintWriter output = new PrintWriter(out);
188         try {
189         while(it.hasNext()) {
190             String strSection = (String) it.next();
191             output.println("[" + strSection + "]");
192             Map section = getSectionEL(strSection);
193             Iterator iit = section.keySet().iterator();
194             while(iit.hasNext()) {
195                 String key = (String) iit.next();
196                 output.println(key + "=" + section.get(key));
197            }
198           }
199         }
200         finally {
201             IOUtil.flushEL(output);
202             IOUtil.closeEL(output);
203             IOUtil.flushEL(out);
204             IOUtil.closeEL(out);
205         }
206     }
207    
208     /**
209      * removes a selection
210      *
211      * @param strSection  section to remove
212      */
213     public void removeSection(String strSection) {
214         sections.remove(strSection);
215     }
216     
217     /**
218      * 
219     * @param file
220     * @return return a struct with all section an dkey list as value
221     * @throws IOException
222     */
223    public static Struct getProfileSections(Resource file) throws IOException {
224         IniFile ini=new IniFile(file);
225         Struct rtn=new StructImpl(Struct.TYPE_SYNC);
226         Map sections = ini.getSections();
227         Iterator it = sections.keySet().iterator();
228         while(it.hasNext()) {
229             String strSection=(String) it.next();
230             Map section = ini.getSectionEL(strSection);
231             Iterator iit = section.keySet().iterator();
232             StringBuilder sb=new StringBuilder();
233             while(iit.hasNext()) {
234                 if(sb.length()!=0)sb.append(',');
235                 sb.append(iit.next());
236             }
237             rtn.setEL(strSection,sb.toString());
238         }
239         return rtn;
240     }
241    }