1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.om.preference.impl;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Locale;
24 import java.util.StringTokenizer;
25 import java.util.prefs.BackingStoreException;
26 import java.util.prefs.Preferences;
27
28 import org.apache.jetspeed.om.common.portlet.MutablePortletApplication;
29 import org.apache.jetspeed.om.common.portlet.MutablePortletEntity;
30 import org.apache.jetspeed.om.common.portlet.PortletDefinitionComposite;
31 import org.apache.jetspeed.om.common.preference.PreferenceComposite;
32 import org.apache.jetspeed.om.impl.PreferenceDescriptionImpl;
33 import org.apache.pluto.om.common.Description;
34
35
36 public class PrefsPreference implements PreferenceComposite
37 {
38 protected static final String VALUES_PATH = "values";
39 protected static final String VALUES_SIZE = "size";
40
41 public static final String PORTLET_PREFERENCES_ROOT = "preferences";
42 protected static final String LOCALE_TOKEN = "_";
43 protected Preferences prefValueNode;
44 protected Preferences prefValueSizeNode;
45 protected Preferences prefNode;
46 protected String name;
47 public static final String[] DEFAULT_OPEN_NODES = new String[] {MutablePortletEntity.PORTLET_ENTITY_ROOT, PortletDefinitionComposite.PORTLETS_PREFS_ROOT};
48
49
50
51 public PrefsPreference(Preferences prefNode, String name)
52 {
53 super();
54 this.prefNode = prefNode;
55 if(prefNode == null)
56 {
57 throw new IllegalArgumentException("prefNode cannot be null for PrefsPreferences(Preference).");
58 }
59
60 this.name = name;
61 if(this.name == null)
62 {
63 throw new IllegalArgumentException("Preference does requires a \"name\" property.");
64 }
65
66 this.prefValueNode = prefNode.node(VALUES_PATH);
67 this.prefValueSizeNode = prefNode.node(VALUES_SIZE);
68 }
69
70 public PrefsPreference(PortletDefinitionComposite portlet, String name)
71 {
72 this(createPrefenceNode(portlet).node(name), name);
73 }
74
75
76 private int getPrefValueSize(boolean store)
77 {
78 int size = prefValueSizeNode.getInt(VALUES_SIZE, -1);
79 if ( size == -1 )
80 {
81
82
83 try
84 {
85 size = prefValueNode.keys().length;
86 }
87 catch (BackingStoreException e)
88 {
89 String msg = "Preference backing store failed: "+e.toString();
90 IllegalStateException ise = new IllegalStateException(msg);
91 ise.initCause(e);
92 throw ise;
93 }
94 if (store)
95 {
96 prefValueSizeNode.putInt(VALUES_SIZE,size);
97 }
98 }
99 return size;
100 }
101
102 /***
103 * <p>
104 * addDescription
105 * </p>
106 *
107 * @see org.apache.jetspeed.om.common.preference.PreferenceComposite#addDescription(java.util.Locale,
108 * java.lang.String)
109 * @param locale
110 * @param Description
111 */
112 public void addDescription( Locale locale, String description )
113 {
114 String localePath = locale.toString();
115 prefNode.node("description").put(localePath, description);
116 }
117
118 /***
119 * <p>
120 * getDescription
121 * </p>
122 *
123 * @see org.apache.jetspeed.om.common.preference.PreferenceComposite#getDescription(java.util.Locale)
124 * @param locale
125 * @return
126 */
127 public Description getDescription( Locale locale )
128 {
129 String localePath = locale.toString();
130 String value = prefNode.node("description").get(localePath, null);
131 PreferenceDescriptionImpl desc = new PreferenceDescriptionImpl();
132 desc.setDescription(value);
133 desc.setLocale(locale);
134 desc.setLanguage(locale.getLanguage());
135 return desc;
136 }
137
138 /***
139 * <p>
140 * getValueAt
141 * </p>
142 *
143 * @see org.apache.jetspeed.om.common.preference.PreferenceComposite#getValueAt(int)
144 * @param index
145 * @return
146 */
147 public String getValueAt( int index )
148 {
149 return prefValueNode.get(String.valueOf(index), null);
150 }
151
152 public void removeValueAt(int index)
153 {
154 int size;
155 if (index > -1 && index < (size = getPrefValueSize(true)) )
156 {
157 String[] values = new String[size-1];
158 for (int i = 0; i < index; i++)
159 {
160 values[i] = prefValueNode.get(String.valueOf(i),null);
161 }
162 for ( int i = index+1; i < size; i++)
163 {
164 values[i] = prefValueNode.get(String.valueOf(i),null);
165 }
166 setValues(values);
167 }
168 else
169 throw new IndexOutOfBoundsException();
170 }
171
172 /***
173 * <p>
174 * setValueAt
175 * </p>
176 *
177 * @see org.apache.jetspeed.om.common.preference.PreferenceComposite#setValueAt(int,
178 * java.lang.String)
179 * @param index
180 * @param value
181 */
182 public void setValueAt( int index, String value )
183 {
184 if ( index > -1 )
185 {
186 int size = getPrefValueSize(true);
187 if ( index < size )
188 {
189 if ( value != null )
190 {
191 prefValueNode.put(String.valueOf(index), value);
192 }
193 else
194 {
195 prefValueNode.remove(String.valueOf(index));
196 }
197 }
198 else
199 {
200 prefValueSizeNode.putInt(VALUES_SIZE, index+1);
201 if ( value != null )
202 {
203 prefValueNode.put(String.valueOf(index),value);
204 }
205 }
206
207 }
208 else
209 throw new IndexOutOfBoundsException();
210 }
211
212 /***
213 * <p>
214 * addValue
215 * </p>
216 *
217 * @see org.apache.jetspeed.om.common.preference.PreferenceComposite#addValue(java.lang.String)
218 * @param value
219 */
220 public void addValue( String value )
221 {
222 int size = getPrefValueSize(true);
223 prefValueSizeNode.putInt(VALUES_SIZE, size+1);
224 if ( value != null )
225 {
226 prefValueNode.put(String.valueOf(size),value);
227 }
228 }
229
230 /***
231 * <p>
232 * getValueArray
233 * </p>
234 *
235 * @see org.apache.jetspeed.om.common.preference.PreferenceComposite#getValueArray()
236 * @return
237 */
238 public String[] getValueArray()
239 {
240 int size = getPrefValueSize(false);
241 String[] values = new String[size];
242 for (int i = 0; i < size; i++)
243 {
244 values[i] = prefValueNode.get(String.valueOf(i),null);
245 }
246 return values;
247 }
248
249 /***
250 * <p>
251 * setValues
252 * </p>
253 *
254 * @see org.apache.jetspeed.om.common.preference.PreferenceComposite#setValues(java.lang.String[])
255 * @param stringValues
256 */
257 public void setValues( String[] stringValues )
258 {
259 try
260 {
261 prefValueNode.clear();
262 int size = stringValues != null ? stringValues.length : 0;
263 prefValueSizeNode.putInt(VALUES_SIZE, size);
264 for (int i = 0; i < size; i++)
265 {
266 if (stringValues[i] != null)
267 {
268 prefValueNode.put(String.valueOf(i), stringValues[i]);
269 }
270 }
271 }
272 catch (BackingStoreException e)
273 {
274 String msg = "Preference backing store failed: "+e.toString();
275 IllegalStateException ise = new IllegalStateException(msg);
276 ise.initCause(e);
277 throw ise;
278 }
279 }
280
281 /***
282 * <p>
283 * getType
284 * </p>
285 *
286 * @see org.apache.jetspeed.om.common.preference.PreferenceComposite#getType()
287 * @return
288 */
289 public String getType()
290 {
291
292 return null;
293 }
294
295 /***
296 * <p>
297 * setType
298 * </p>
299 *
300 * @see org.apache.jetspeed.om.common.preference.PreferenceComposite#setType(java.lang.String)
301 * @param string
302 */
303 public void setType( String string )
304 {
305
306
307 }
308
309 /***
310 * <p>
311 * setName
312 * </p>
313 *
314 * @see org.apache.pluto.om.common.PreferenceCtrl#setName(java.lang.String)
315 * @param arg0
316 */
317 public void setName( String name )
318 {
319 this.name = name;
320
321 }
322
323 /***
324 * <p>
325 * setValues
326 * </p>
327 *
328 * @see org.apache.pluto.om.common.PreferenceCtrl#setValues(java.util.List)
329 * @param arg0
330 */
331 public void setValues( List arg0 )
332 {
333 if (arg0 != null)
334 {
335 setValues((String[]) arg0.toArray(new String[arg0.size()]));
336 }
337
338 }
339
340 /***
341 * <p>
342 * setReadOnly
343 * </p>
344 *
345 * @see org.apache.pluto.om.common.PreferenceCtrl#setReadOnly(java.lang.String)
346 * @param arg0
347 */
348 public void setReadOnly( String readOnly )
349 {
350 prefNode.put("read_only", readOnly);
351
352 }
353
354 public void setReadOnly( boolean readOnly )
355 {
356 if(readOnly)
357 {
358 prefNode.put("read_only", "true");
359 }
360 else
361 {
362 prefNode.put("read_only", "false");
363 }
364
365 }
366
367 /***
368 * <p>
369 * getName
370 * </p>
371 *
372 * @see org.apache.pluto.om.common.Preference#getName()
373 * @return
374 */
375 public String getName()
376 {
377 return name;
378 }
379
380 /***
381 * <p>
382 * getValues
383 * </p>
384 *
385 * @see org.apache.pluto.om.common.Preference#getValues()
386 * @return
387 */
388 public Iterator getValues()
389 {
390 return Arrays.asList(getValueArray()).iterator();
391 }
392
393 /***
394 * <p>
395 * isReadOnly
396 * </p>
397 *
398 * @see org.apache.pluto.om.common.Preference#isReadOnly()
399 * @return
400 */
401 public boolean isReadOnly()
402 {
403 return Boolean.valueOf(prefNode.get("read_only", "false")).booleanValue();
404 }
405
406 /***
407 * <p>
408 * isValueSet
409 * </p>
410 *
411 * @see org.apache.pluto.om.common.Preference#isValueSet()
412 * @return
413 */
414 public boolean isValueSet()
415 {
416 return getPrefValueSize(false) > 0;
417 }
418
419 protected Locale parseLocal( String localString )
420 {
421 StringTokenizer lcTk = new StringTokenizer(localString, LOCALE_TOKEN);
422 String lang = null;
423 String country = null;
424 String variant = null;
425 while (lcTk.hasMoreTokens())
426 {
427 if (lang == null)
428 {
429 lang = lcTk.nextToken();
430 }
431 else if (country == null)
432 {
433 country = lcTk.nextToken();
434 }
435 else if (variant == null)
436 {
437 variant = lcTk.nextToken();
438 }
439 }
440
441 return new Locale(lang, country, variant);
442 }
443
444
445 /***
446 * <p>
447 * clone
448 * </p>
449 *
450 * @see java.lang.Object#clone()
451 * @return @throws
452 * java.lang.CloneNotSupportedException
453 */
454 public String[] cloneValues()
455 {
456 String[] clonedValues;
457 synchronized (prefValueNode)
458 {
459 String[] currentValues = getValueArray();
460 clonedValues = new String[currentValues.length];
461
462 System.arraycopy(currentValues, 0, clonedValues, 0, currentValues.length);
463 }
464
465 return clonedValues;
466 }
467
468 /***
469 * <p>
470 * equals
471 * </p>
472 *
473 * @see java.lang.Object#equals(java.lang.Object)
474 * @param obj
475 * @return
476 */
477 public boolean equals( Object obj )
478 {
479 if (obj != null && obj instanceof PrefsPreference && name != null)
480 {
481 PrefsPreference pref = (PrefsPreference) obj;
482 return pref.name != null && this.name.equals(pref.name);
483
484 }
485 else
486 {
487 return false;
488 }
489
490 }
491
492 /***
493 * <p>
494 * hashCode
495 * </p>
496 *
497 * @see java.lang.Object#hashCode()
498 * @return
499 */
500 public int hashCode()
501 {
502 return (getClass().getName()+"::"+name).hashCode();
503 }
504
505 /***
506 * <p>
507 * toString
508 * </p>
509 *
510 * @see java.lang.Object#toString()
511 * @return
512 */
513 public String toString()
514 {
515 return "Preference{"+name+"} values="+getValueArray().toString();
516 }
517
518 /***
519 *
520 */
521 public void flush() throws BackingStoreException
522 {
523 prefValueNode.flush();
524 }
525 /***
526 * <p>
527 * getDescriptions
528 * </p>
529 *
530 * @see org.apache.jetspeed.om.common.preference.PreferenceComposite#getDescriptions()
531 * @return
532 */
533 public Iterator getDescriptions()
534 {
535 try
536 {
537 Preferences descNode = prefNode.node("description");
538
539 String[] keys = descNode.keys();
540 ArrayList descs = new ArrayList(keys.length);
541 for(int i=0; i < keys.length; i++)
542 {
543 PreferenceDescriptionImpl desc = new PreferenceDescriptionImpl();
544 String localeKey = keys[i];
545 desc.setDescription(descNode.get(localeKey, null));
546 Locale locale = parseLocal(localeKey);
547 desc.setLocale(locale);
548 desc.setLanguage(locale.getLanguage());
549 descs.add(desc);
550 }
551
552 return descs.iterator();
553 }
554 catch (BackingStoreException e)
555 {
556 String msg = "Preference backing store failed: "+e.toString();
557 IllegalStateException ise = new IllegalStateException(msg);
558 ise.initCause(e);
559 throw ise;
560 }
561 }
562
563 /***
564 *
565 * <p>
566 * createPrefenceNode
567 * </p>
568 *
569 * Creates a Preferences object for this portlet
570 *
571 * @param portlet
572 * @return
573 */
574
575 public static Preferences createPrefenceNode(PortletDefinitionComposite portlet)
576 {
577 MutablePortletApplication app = (MutablePortletApplication) portlet.getPortletApplicationDefinition();
578 if(app == null)
579 {
580 throw new IllegalArgumentException("createPrefencePath() requires a PortletDefinition whose Application is not null.");
581 }
582 String portletDefPrefPath = MutablePortletApplication.PREFS_ROOT + "/" + app.getName() + "/"
583 + PortletDefinitionComposite.PORTLETS_PREFS_ROOT + "/" + portlet.getName() + "/"
584 + PrefsPreference.PORTLET_PREFERENCES_ROOT;
585
586 return Preferences.systemRoot().node(portletDefPrefPath);
587 }
588 }