1 | // Copyright 2004-2007 Jean-Francois Poilpret |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | package net.sourceforge.hiveutils.util; |
16 | |
17 | import java.util.Collections; |
18 | import java.util.HashMap; |
19 | import java.util.Iterator; |
20 | import java.util.Map; |
21 | import java.util.prefs.Preferences; |
22 | |
23 | import org.apache.commons.logging.Log; |
24 | import org.apache.commons.logging.LogFactory; |
25 | import org.apache.hivemind.util.ConstructorUtils; |
26 | import org.apache.hivemind.util.PropertyUtils; |
27 | |
28 | /** |
29 | * Utility class to load/store beans to the preferences store. |
30 | * |
31 | * @author Jean-Francois Poilpret |
32 | */ |
33 | final public class PreferencesUtils |
34 | { |
35 | static private final Log _logger = LogFactory.getLog(PreferencesUtils.class); |
36 | |
37 | private PreferencesUtils() |
38 | { |
39 | } |
40 | |
41 | static public Object load(String name, Class beanClass, PrefType type) |
42 | { |
43 | return load(name, beanClass, type, EMPTY_MAP); |
44 | } |
45 | |
46 | static public Object load( String name, |
47 | Class beanClass, |
48 | PrefType type, |
49 | Map<Class, PrefsMapper> mappers) |
50 | { |
51 | // Instantiate the Object |
52 | Object pref = ConstructorUtils.invokeConstructor(beanClass, null); |
53 | // Find prefs node |
54 | Preferences root; |
55 | if (type == PrefType.SYSTEM) |
56 | { |
57 | root = Preferences.systemRoot(); |
58 | } |
59 | else |
60 | { |
61 | root = Preferences.userRoot(); |
62 | } |
63 | // Read (or create) the node in the prefs repository |
64 | root = root.node(name); |
65 | // Get the list of writable properties of the target object |
66 | Iterator props = PropertyUtils.getWriteableProperties(pref).iterator(); |
67 | // For each property, get its value from the node in the prefs repository |
68 | while (props.hasNext()) |
69 | { |
70 | String prop = (String) props.next(); |
71 | Class clazz = PropertyUtils.getPropertyType(pref, prop); |
72 | // Find a mapper for this kind of property |
73 | PrefsMapper mapper = findMapper(clazz, mappers); |
74 | if (mapper == null) |
75 | { |
76 | // No existing mapper, keep default value for that property |
77 | if (_logger.isDebugEnabled()) |
78 | { |
79 | _logger.debug( "instantiate(" + name + |
80 | ") no mapper for " + beanClass + "." + |
81 | prop + " (type = " + clazz + ")"); |
82 | } |
83 | continue; |
84 | } |
85 | // Get value from preference node |
86 | String value = root.get(prop, null); |
87 | if (value != null) |
88 | { |
89 | // Ask mapper to convert value into object |
90 | Object realValue = mapper.read(value); |
91 | // Write the actual value to the bean property |
92 | PropertyUtils.write(pref, prop, realValue); |
93 | } |
94 | } |
95 | return pref; |
96 | } |
97 | |
98 | static public void store(String name, PrefType type, Object pref) |
99 | { |
100 | store(name, type, pref, EMPTY_MAP); |
101 | } |
102 | |
103 | static public void store( String name, |
104 | PrefType type, |
105 | Object pref, |
106 | Map<Class, PrefsMapper> mappers) |
107 | { |
108 | // Find prefs node |
109 | Preferences root; |
110 | if (type == PrefType.SYSTEM) |
111 | { |
112 | root = Preferences.systemRoot(); |
113 | } |
114 | else |
115 | { |
116 | root = Preferences.userRoot(); |
117 | } |
118 | // Read (or create) the node in the prefs repository |
119 | root = root.node(name); |
120 | // Get the list of writable properties of the target object |
121 | Iterator props = PropertyUtils.getWriteableProperties(pref).iterator(); |
122 | // For each property, write its value into the node in the prefs repository |
123 | while (props.hasNext()) |
124 | { |
125 | String prop = (String) props.next(); |
126 | Class clazz = PropertyUtils.getPropertyType(pref, prop); |
127 | // Find a mapper for this kind of property |
128 | PrefsMapper mapper = findMapper(clazz, mappers); |
129 | if (mapper == null) |
130 | { |
131 | // No existing mapper, do not write that property |
132 | continue; |
133 | } |
134 | // Get bean property value |
135 | Object realValue = PropertyUtils.read(pref, prop); |
136 | // Ask mapper to convert value into string |
137 | String value = mapper.write(realValue); |
138 | if (value != null) |
139 | { |
140 | // Put value to preference node |
141 | root.put(prop, value); |
142 | } |
143 | } |
144 | } |
145 | |
146 | static protected PrefsMapper findMapper( Class clazz, |
147 | Map<Class, PrefsMapper> mappers) |
148 | { |
149 | PrefsMapper mapper = mappers.get(clazz); |
150 | if (mapper != null) |
151 | { |
152 | return mapper; |
153 | } |
154 | return _basicMappers.get(clazz); |
155 | } |
156 | |
157 | static private final Map<Class, PrefsMapper> _basicMappers = |
158 | new HashMap<Class, PrefsMapper>(); |
159 | static private final Map<Class, PrefsMapper> EMPTY_MAP = Collections.emptyMap(); |
160 | |
161 | static |
162 | { |
163 | // Initialize standard mappers |
164 | _basicMappers.put(int.class, new IntMapper()); |
165 | _basicMappers.put(Integer.class, new IntMapper()); |
166 | _basicMappers.put(long.class, new LongMapper()); |
167 | _basicMappers.put(Long.class, new LongMapper()); |
168 | _basicMappers.put(float.class, new FloatMapper()); |
169 | _basicMappers.put(Float.class, new FloatMapper()); |
170 | _basicMappers.put(double.class, new DoubleMapper()); |
171 | _basicMappers.put(Double.class, new DoubleMapper()); |
172 | _basicMappers.put(boolean.class, new BooleanMapper()); |
173 | _basicMappers.put(Boolean.class, new BooleanMapper()); |
174 | _basicMappers.put(String.class, new StringMapper()); |
175 | } |
176 | } |
177 | |
178 | // Standard mappers |
179 | abstract class AbstractMapper implements PrefsMapper |
180 | { |
181 | public String write(Object o) |
182 | { |
183 | if (o == null) |
184 | { |
185 | return null; |
186 | } |
187 | else |
188 | { |
189 | return o.toString(); |
190 | } |
191 | } |
192 | } |
193 | class IntMapper extends AbstractMapper |
194 | { |
195 | public Object read(String s) |
196 | { |
197 | return Integer.decode(s); |
198 | } |
199 | } |
200 | class LongMapper extends AbstractMapper |
201 | { |
202 | public Object read(String s) |
203 | { |
204 | return Long.decode(s); |
205 | } |
206 | } |
207 | class BooleanMapper extends AbstractMapper |
208 | { |
209 | public Object read(String s) |
210 | { |
211 | return Boolean.valueOf(s); |
212 | } |
213 | } |
214 | class FloatMapper extends AbstractMapper |
215 | { |
216 | public Object read(String s) |
217 | { |
218 | return Float.valueOf(s); |
219 | } |
220 | } |
221 | class DoubleMapper extends AbstractMapper |
222 | { |
223 | public Object read(String s) |
224 | { |
225 | return Double.valueOf(s); |
226 | } |
227 | } |
228 | class StringMapper implements PrefsMapper |
229 | { |
230 | public String write(Object o) |
231 | { |
232 | return (String) o; |
233 | } |
234 | public Object read(String s) |
235 | { |
236 | return s; |
237 | } |
238 | } |