001 /* 002 * Copyright 2005 [ini4j] Development Team 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of 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, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.ini4j; 018 019 import java.util.prefs.*; 020 import java.io.*; 021 import java.net.URL; 022 023 public class IniPreferences extends AbstractPreferences 024 { 025 /** frequently used empty String array */ 026 private static final String[] EMPTY = {}; 027 028 /** underlaying <code>Ini</code> implementation */ 029 private Ini _ini; 030 031 protected class SectionPreferences extends AbstractPreferences 032 { 033 /** underlaying <code>Section</code> implementation */ 034 private Ini.Section _section; 035 036 /** 037 * Constructs a new SectionPreferences instance on top of Ini.Section instance. 038 * 039 * @param parent parent preferences node 040 * @parem section underlaying Ini.Section instance 041 * @param isNew indicate is this a new node or already existing one 042 */ 043 SectionPreferences(IniPreferences parent, Ini.Section section, boolean isNew) 044 { 045 super(parent, section.getName()); 046 _section = section; 047 newNode = isNew; 048 } 049 050 /** 051 * Implements the <CODE>childSpi</CODE> method as per the specification in 052 * {@link java.util.prefs.AbstractPreferences#childSpi(String)}. 053 * 054 * This implementation doesn't support this operation. 055 * 056 * @throws UnsupportedOperationException this implementation allways throws this exception 057 * @param name child name 058 * @return child node 059 */ 060 protected AbstractPreferences childSpi(String name) throws UnsupportedOperationException 061 { 062 throw new UnsupportedOperationException(); 063 } 064 065 /** 066 * Implements the <CODE>childrenNamesSpi</CODE> method as per the specification in 067 * {@link java.util.prefs.AbstractPreferences#childrenNamesSpi()}. 068 * 069 * This implementation allways returns an empty array. 070 * 071 * @return an emty array. 072 * @throws BackingStoreException if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it. 073 */ 074 protected String[] childrenNamesSpi() throws BackingStoreException 075 { 076 return EMPTY; 077 } 078 079 /** 080 * Implements the <CODE>flushSpi</CODE> method as per the specification in 081 * {@link java.util.prefs.AbstractPreferences#flushSpi()}. 082 * 083 * This implementation does nothing. 084 * 085 * @throws BackingStoreException if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it. 086 */ 087 protected void flushSpi() throws BackingStoreException 088 { 089 ; 090 } 091 092 /** 093 * Implements the <CODE>getSpi</CODE> method as per the specification in 094 * {@link java.util.prefs.AbstractPreferences#getSpi(String)}. 095 * @return if the value associated with the specified key at this preference node, or null if there is no association for this key, or the association cannot be determined at this time. 096 * @param key key to getvalue for 097 */ 098 protected String getSpi(String key) 099 { 100 return _section.fetch(key); 101 } 102 103 /** 104 * Implements the <CODE>keysSpi</CODE> method as per the specification in 105 * {@link java.util.prefs.AbstractPreferences#keysSpi()}. 106 * 107 * @return an array of the keys that have an associated value in this preference node. 108 * @throws BackingStoreException if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it. 109 */ 110 protected String[] keysSpi() throws BackingStoreException 111 { 112 return _section.keySet().toArray(EMPTY); 113 } 114 115 /** 116 * Implements the <CODE>putSpi</CODE> method as per the specification in 117 * {@link java.util.prefs.AbstractPreferences#putSpi(String,String)}. 118 * 119 * @param key key to set value for 120 * @param value new value of key 121 */ 122 protected void putSpi(String key, String value) 123 { 124 _section.put(key, value); 125 } 126 127 /** 128 * Implements the <CODE>removeNodeSpi</CODE> method as per the specification in 129 * {@link java.util.prefs.AbstractPreferences#removeNodeSpi()}. 130 * 131 * @throws BackingStoreException if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it. 132 */ 133 protected void removeNodeSpi() throws BackingStoreException 134 { 135 _ini.remove(_section); 136 } 137 138 /** 139 * Implements the <CODE>removeSpi</CODE> method as per the specification in 140 * {@link java.util.prefs.AbstractPreferences#removeSpi(String)}. 141 * @param key key to remove 142 */ 143 protected void removeSpi(String key) 144 { 145 _section.remove(key); 146 } 147 148 /** 149 * Implements the <CODE>syncSpi</CODE> method as per the specification in 150 * {@link java.util.prefs.AbstractPreferences#syncSpi()}. 151 * 152 * This implementation does nothing. 153 * 154 * @throws BackingStoreException if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it. 155 */ 156 protected void syncSpi() throws BackingStoreException 157 { 158 ; 159 } 160 161 /** 162 * Implements the <CODE>sync</CODE> method as per the specification in 163 * {@link java.util.prefs.Preferences#sync()}. 164 * 165 * This implementation just call parent's <code>sync()</code> method. 166 * 167 * @throws BackingStoreException if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it. 168 */ 169 public void sync() throws BackingStoreException 170 { 171 parent().sync(); 172 } 173 174 /** 175 * Implements the <CODE>flush</CODE> method as per the specification in 176 * {@link java.util.prefs.Preferences#flush()}. 177 * 178 * This implementation just call parent's <code>flush()</code> method. 179 * 180 * @throws BackingStoreException if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it. 181 */ 182 public void flush() throws BackingStoreException 183 { 184 parent().flush(); 185 } 186 } 187 188 /** 189 * Constructs a new preferences node on top of <code>Ini</code> instance. 190 * 191 * @param ini underlaying <code>Ini</code> instance 192 */ 193 public IniPreferences(Ini ini) 194 { 195 super(null, ""); 196 _ini = ini; 197 } 198 199 /** 200 * Constructs a new preferences node based on newly loaded <code>Ini</code> instance. 201 * 202 * This is just a helper constructor, to make simpler constructing <code>IniPreferences</code> 203 * directly from <code>Reader</code>. 204 * 205 * @param input the <code>Reader</code> containing <code>Ini</code> data 206 * @throws IOException if an I/O error occured 207 * @throws InvalidIniFormatException if <code>Ini</code> parsing error occured 208 */ 209 public IniPreferences(Reader input) throws IOException, InvalidIniFormatException 210 { 211 super(null, ""); 212 _ini = new Ini(input); 213 } 214 215 /** 216 * Constructs a new preferences node based on newly loaded <code>Ini</code> instance. 217 * 218 * This is just a helper constructor, to make simpler constructing <code>IniPreferences</code> 219 * directly from <code>InputStream</code>. 220 * 221 * @param input the <code>InputStream</code> containing <code>Ini</code> data 222 * @throws IOException if an I/O error occured 223 * @throws InvalidIniFormatException if <code>Ini</code> parsing error occured 224 */ 225 public IniPreferences(InputStream input) throws IOException, InvalidIniFormatException 226 { 227 super(null, ""); 228 _ini = new Ini(input); 229 } 230 231 /** 232 * Constructs a new preferences node based on newly loaded <code>Ini</code> instance. 233 * 234 * This is just a helper constructor, to make simpler constructing <code>IniPreferences</code> 235 * directly from <code>URL</code>. 236 * 237 * @param input the <code>URL</code> containing <code>Ini</code> data 238 * @throws IOException if an I/O error occured 239 * @throws InvalidIniFormatException if <code>Ini</code> parsing error occured 240 */ 241 public IniPreferences(URL input) throws IOException, InvalidIniFormatException 242 { 243 super(null, ""); 244 _ini = new Ini(input); 245 } 246 247 /** 248 * Implements the <CODE>childSpi</CODE> method as per the specification in 249 * {@link java.util.prefs.AbstractPreferences#childSpi(String)}. 250 * @param name child name 251 * @return child node 252 */ 253 protected AbstractPreferences childSpi(String name) 254 { 255 Ini.Section sec = _ini.get(name); 256 boolean isNew = sec == null; 257 258 if ( isNew ) 259 { 260 sec = _ini.add(name); 261 } 262 263 return new SectionPreferences(this, sec, isNew); 264 } 265 266 /** 267 * Implements the <CODE>childrenNamesSpi</CODE> method as per the specification in 268 * {@link java.util.prefs.AbstractPreferences#childrenNamesSpi()}. 269 * @return an array containing the names of the children of this preference node. 270 * @throws BackingStoreException if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it. 271 */ 272 protected String[] childrenNamesSpi() throws BackingStoreException 273 { 274 return _ini.keySet().toArray(EMPTY); 275 } 276 277 /** 278 * Implements the <CODE>flushSpi</CODE> method as per the specification in 279 * {@link java.util.prefs.AbstractPreferences#flushSpi()}. 280 * 281 * This implementation does nothing. 282 * 283 * @throws BackingStoreException if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it. 284 */ 285 protected void flushSpi() throws BackingStoreException 286 { 287 ; 288 } 289 290 /** 291 * Implements the <CODE>getSpi</CODE> method as per the specification in 292 * {@link java.util.prefs.AbstractPreferences#getSpi(String)}. 293 * 294 * This implementation doesn't support this operation, so allways throws UnsupportedOperationException. 295 * 296 * @return if the value associated with the specified key at this preference node, or null if there is no association for this key, or the association cannot be determined at this time. 297 * @param key key to getvalue for 298 * @throws UnsupportedOperationException this implementation allways throws this exception 299 */ 300 protected String getSpi(String key) throws UnsupportedOperationException 301 { 302 throw new UnsupportedOperationException(); 303 } 304 305 /** 306 * Implements the <CODE>keysSpi</CODE> method as per the specification in 307 * {@link java.util.prefs.AbstractPreferences#keysSpi()}. 308 * 309 * This implementation allways return an empty array. 310 * 311 * @return an empty array. 312 * @throws BackingStoreException if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it. 313 */ 314 protected String[] keysSpi() throws BackingStoreException 315 { 316 return EMPTY; 317 } 318 319 /** 320 * Implements the <CODE>putSpi</CODE> method as per the specification in 321 * {@link java.util.prefs.AbstractPreferences#putSpi(String,String)}. 322 * 323 * This implementation doesn;t support this operation, so allways throws UnsupportedOperationException. 324 * 325 * @param key key to set value for 326 * @param value new value for key 327 * @throws UnsupportedOperationException this implementation allways throws this exception 328 */ 329 protected void putSpi(String key, String value) throws UnsupportedOperationException 330 { 331 throw new UnsupportedOperationException(); 332 } 333 334 /** 335 * Implements the <CODE>removeNodeSpi</CODE> method as per the specification in 336 * {@link java.util.prefs.AbstractPreferences#removeNodeSpi()}. 337 * 338 * This implementation doesn;t support this operation, so allways throws UnsupportedOperationException. 339 * @throws UnsupportedOperationException this implementation allways throws this exception 340 * @throws BackingStoreException this implementation never throws this exception 341 */ 342 protected void removeNodeSpi() throws BackingStoreException, UnsupportedOperationException 343 { 344 throw new UnsupportedOperationException(); 345 } 346 347 /** 348 * Implements the <CODE>removeSpi</CODE> method as per the specification in 349 * {@link java.util.prefs.AbstractPreferences#removeSpi(String)}. 350 * @param key key to remove 351 * @throws UnsupportedOperationException this implementation allways throws this exception 352 */ 353 protected void removeSpi(String key) throws UnsupportedOperationException 354 { 355 throw new UnsupportedOperationException(); 356 } 357 358 /** 359 * Implements the <CODE>syncSpi</CODE> method as per the specification in 360 * {@link java.util.prefs.AbstractPreferences#syncSpi()}. 361 * 362 * This implementation does nothing. 363 * 364 * @throws BackingStoreException if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it. 365 */ 366 protected void syncSpi() throws BackingStoreException 367 { 368 ; 369 } 370 371 /** 372 * Provide access to underlaying {@link org.ini4j.Ini} implementation. 373 * 374 * @return <code>Ini</code> implementation 375 */ 376 protected Ini getIni() 377 { 378 return _ini; 379 } 380 }