1 package com.explosion.utilities.preferences.impl.sun;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.awt.Color;
24 import java.awt.Font;
25 import java.io.File;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.prefs.BackingStoreException;
29 import java.util.prefs.Preferences;
30
31 import com.explosion.utilities.GeneralConstants;
32 import com.explosion.utilities.preferences.EncryptionException;
33 import com.explosion.utilities.preferences.Preference;
34 import com.explosion.utilities.preferences.groups.PreferencePersistenceException;
35 import com.explosion.utilities.preferences.persist.PreferencePersister;
36
37 /***
38 * @author: Stephen Cowx
39 *
40 * A persister to allow preferences to be persisted using the Java Preferences API
41 *
42 */
43
44 public class SunPreferencePersister implements PreferencePersister
45 {
46 private Preferences parentNode;
47
48 /***
49 * Hidden constructor, want to use the factory method
50 */
51 private SunPreferencePersister() {
52 }
53
54 /***
55 * Constructs an instance of a SunPreferencePersistor
56 * @param referenceToStore
57 * @return
58 */
59 public static PreferencePersister createPreferencePersistor(Object referenceToStore)
60 {
61 SunPreferencePersister persister = new SunPreferencePersister();
62 persister.parentNode = (Preferences) referenceToStore;
63 return persister;
64 }
65
66 /***
67 * Returns a reference to the backing store as understood by the PreferencePersister
68 * @return
69 */
70 public Object getReferenceToStore()
71 {
72 return parentNode;
73 }
74
75 /***
76 * Sets the reference to the backing store as understood by the PreferencePersister
77 * Effectively moving it from one store to another or moving it from one location in the same store to another
78 * @return
79 */
80 public void setReferenceToStore(Object referenceToStore)
81 {
82 this.parentNode = (Preferences) referenceToStore;
83 }
84
85 /***
86 * This method saves the property to persistent storage, if the value is
87 * null, it should delete the entire key/value pair persisted if it exists
88 * or not save it if it does.
89 *
90 * @throws Exception
91 */
92 public void save(Preference preference) throws PreferencePersistenceException
93 {
94 if (preference.isDefaulted())
95 {
96
97 if (parentNode.get(preference.getUniqueIdentifier(), null) != null)
98 parentNode.remove(preference.getUniqueIdentifier());
99
100 return;
101 }
102
103 if (preference.getType() == Preference.PROPERTY_TYPE_COLLECTION)
104 persistCollection(preference);
105 else
106 persistPreference(preference.getType(), preference.getUniqueIdentifier(), preference.getValue(), parentNode);
107
108 try {
109 parentNode.flush();
110 } catch (BackingStoreException e) {
111 throw new PreferencePersistenceException("Exception caught while flushing Preferences node.", e);
112 }
113 }
114
115 /***
116 * @throws Exception
117 */
118 private void persistPreference(int type, String uniqueId, Object theValue, Preferences node) throws PreferencePersistenceException
119 {
120 try
121 {
122 switch (type)
123 {
124 case (Preference.PROPERTY_TYPE_TEXT):
125 node.put(uniqueId, (String) theValue);
126 break;
127 case (Preference.PROPERTY_TYPE_FILE):
128 node.put(uniqueId, ((File) theValue).getAbsolutePath());
129 break;
130 case (Preference.PROPERTY_TYPE_DIRECTORY):
131 node.put(uniqueId, ((File) theValue).getAbsolutePath());
132 break;
133 case (Preference.PROPERTY_TYPE_COLOR):
134 node.putInt(uniqueId, ((Color) theValue).getRGB());
135 break;
136 case (Preference.PROPERTY_TYPE_INT):
137 node.putInt(uniqueId, ((Integer) theValue).intValue());
138 break;
139 case (Preference.PROPERTY_TYPE_FLOAT):
140 node.putFloat(uniqueId, ((Float) theValue).floatValue());
141 break;
142 case (Preference.PROPERTY_TYPE_STRING_CHOICE):
143 node.put(uniqueId, ((String) theValue));
144 break;
145 case (Preference.PROPERTY_TYPE_INT_CHOICE):
146 node.putInt(uniqueId, ((Integer) theValue).intValue());
147 break;
148 case (Preference.PROPERTY_TYPE_BOOLEAN):
149 node.putBoolean(uniqueId, ((Boolean) theValue).booleanValue());
150 break;
151 case (Preference.PROPERTY_TYPE_FONT):
152 String fontString = ((Font) theValue).getStyle() + "," + ((Font) theValue).getSize() + "," + ((Font) theValue).getName();
153 node.put(uniqueId, fontString);
154 break;
155 case (Preference.PROPERTY_TYPE_ENCRYPTED):
156
157 node.put(uniqueId, Preference.encrypt((String) theValue));
158 break;
159 case (Preference.PROPERTY_TYPE_COLLECTION):
160 throw new IllegalArgumentException("Unexpected type : COLLECTION.");
161 }
162 }
163 catch (EncryptionException e)
164 {
165 throw new PreferencePersistenceException("Exception caught while persisting preference", e);
166 }
167 }
168
169 /***
170 * Creates a new node for this collection and adds the children into it
171 *
172 * @param preferences
173 */
174 private void persistCollection(Preference preference) throws PreferencePersistenceException
175 {
176 try
177 {
178 Preferences collectionNode = parentNode.node(preference.getUniqueIdentifier());
179 collectionNode.clear();
180
181 List items = preference.getValues();
182 collectionNode.putInt(ITEM_COUNT, items.size());
183 for (int i = 0; i < items.size(); i++)
184 {
185 persistPreference(preference.getCollectionType(), ITEM_NAME + i, items.get(i), collectionNode);
186 }
187 }
188 catch (BackingStoreException e)
189 {
190 throw new PreferencePersistenceException("Exception caught while saving preference " + preference.getLongName(), e);
191 }
192 }
193
194 /***
195 * This method loads the property from persistent storage if it is there, if
196 * it is not it should not populate the value.
197 *
198 * @throws Exception
199 */
200 public void load(Preference preference) throws PreferencePersistenceException
201 {
202 try
203 {
204 if (preference.getType() != Preference.PROPERTY_TYPE_COLLECTION)
205 {
206 if (parentNode.get(preference.getUniqueIdentifier(), null) == null)
207 return;
208
209 Object object = getTypedValue(preference.getType(), parentNode, preference.getUniqueIdentifier(), preference.getDefaultValue());
210 preference.setValue(object);
211
212
213 switch (preference.getType())
214 {
215 case (Preference.PROPERTY_TYPE_FILE):
216 if (((File) preference.getValue()).getName().indexOf(GeneralConstants.DEFAULT_FILE) >= 0)
217 preference.setValue(preference.createDefaultFile());
218 break;
219 case (Preference.PROPERTY_TYPE_DIRECTORY):
220 if (((File) preference.getValue()).getName().equals(GeneralConstants.DEFAULT_FILE))
221 preference.setValue(preference.createDefaultFile());
222 break;
223 }
224 }
225 else
226 {
227 loadCollection(preference);
228 }
229 }
230 catch (PreferencePersistenceException e)
231 {
232 throw e;
233 }
234 catch (Exception e)
235 {
236 throw new PreferencePersistenceException("Error caught while persisting data", e);
237 }
238 }
239
240 /***
241 * Obtains and creates the object from the persistent store based on it's
242 * type
243 *
244 * @param type
245 * @param node
246 * @param uniqueIdentifier
247 * @param defaultValue
248 * @return @throws Exception
249 */
250 private Object getTypedValue(int type, Preferences node, String uniqueIdentifier, Object defaultValue) throws PreferencePersistenceException
251 {
252 try
253 {
254 switch (type)
255 {
256 case (Preference.PROPERTY_TYPE_TEXT):
257 return node.get(uniqueIdentifier, (String) defaultValue);
258 case (Preference.PROPERTY_TYPE_FILE):
259 return new File(node.get(uniqueIdentifier, ((File) defaultValue).toString()));
260 case (Preference.PROPERTY_TYPE_DIRECTORY):
261 return new File(node.get(uniqueIdentifier, ((File) defaultValue).toString()));
262 case (Preference.PROPERTY_TYPE_COLOR):
263 return new Color(node.getInt(uniqueIdentifier, ((Color) defaultValue).getRGB()));
264 case (Preference.PROPERTY_TYPE_INT):
265 return new Integer(node.getInt(uniqueIdentifier, ((Integer) defaultValue).intValue()));
266 case (Preference.PROPERTY_TYPE_FLOAT):
267 return new Float(node.getFloat(uniqueIdentifier, ((Float) defaultValue).floatValue()));
268 case (Preference.PROPERTY_TYPE_STRING_CHOICE):
269 return getTypedValue(Preference.PROPERTY_TYPE_TEXT, node, uniqueIdentifier, defaultValue);
270 case (Preference.PROPERTY_TYPE_INT_CHOICE):
271 return getTypedValue(Preference.PROPERTY_TYPE_INT, node, uniqueIdentifier, defaultValue);
272 case (Preference.PROPERTY_TYPE_BOOLEAN):
273 return new Boolean(node.getBoolean(uniqueIdentifier, ((Boolean) defaultValue).booleanValue()));
274 case (Preference.PROPERTY_TYPE_FONT):
275 String defaultFontString = ((Font) defaultValue).getStyle() + "," + ((Font) defaultValue).getSize() + "," + ((Font) defaultValue).getName();
276 return Preference.deriveFont(node.get(uniqueIdentifier, defaultFontString));
277 case (Preference.PROPERTY_TYPE_ENCRYPTED):
278
279 return Preference.decrypt(node.get(uniqueIdentifier, (String) defaultValue));
280 default:
281 return null;
282 }
283 }
284 catch (PreferencePersistenceException e)
285 {
286 throw e;
287 }
288 catch (EncryptionException e)
289 {
290 throw new PreferencePersistenceException("Error caught while persisting data", e);
291 }
292 }
293
294 /***
295 * loads this collection into the values List
296 *
297 * @param preferences
298 */
299 private void loadCollection(Preference preference) throws Exception
300 {
301 Preferences collectionNode = parentNode.node(preference.getUniqueIdentifier());
302 int numberOfItems = collectionNode.getInt(ITEM_COUNT, -1);
303 if (numberOfItems == -1)
304 return;
305
306 List items = new ArrayList();
307
308 for (int i = 0; i < numberOfItems; i++)
309 {
310 items.add(getTypedValue(preference.getCollectionType(), collectionNode, ITEM_NAME + i, preference.getDefaultValue()));
311 }
312
313 preference.setValues(items, preference.getCollectionType());
314 }
315
316 }