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 }