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