001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.om.preference.impl;
018:
019: import java.util.Arrays;
020: import java.util.ConcurrentModificationException;
021: import java.util.HashSet;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Set;
025: import java.util.Vector;
026: import java.util.prefs.BackingStoreException;
027: import java.util.prefs.Preferences;
028:
029: import javax.portlet.PreferencesValidator;
030:
031: import org.apache.jetspeed.om.common.preference.PreferenceSetComposite;
032: import org.apache.jetspeed.om.common.preference.PreferencesValidatorFactory;
033: import org.apache.pluto.om.common.Preference;
034:
035: /**
036: * @author <a href="mailto:weaver@apache.org">Scott T. Weaver </a>
037: *
038: *
039: */
040: public class PrefsPreferenceSetImpl implements PreferenceSetComposite {
041: protected Preferences prefsRootNode;
042: protected PreferenceSetComposite defaults;
043: protected PreferencesValidatorFactory validatorFactory;
044:
045: /**
046: * @param portletEntity
047: * PortletEntity for which to build the PreferenceSet for.
048: * @throws BackingStoreException
049: * if an error is encountered while accessing the Preferences
050: * backing store.
051: */
052: public PrefsPreferenceSetImpl(Preferences prefsRootNode)
053: throws BackingStoreException {
054: super ();
055: this .prefsRootNode = prefsRootNode;
056:
057: }
058:
059: /**
060: * @param portletEntity
061: * PortletEntity for which to build the PreferenceSet for.
062: * @param validatorFactory
063: * Factory for providing access to a PreferencesValidator instance
064: * @throws BackingStoreException
065: * if an error is encountered while accessing the Preferences
066: * backing store.
067: */
068: public PrefsPreferenceSetImpl(Preferences prefsRootNode,
069: PreferencesValidatorFactory validatorFactory)
070: throws BackingStoreException {
071: this (prefsRootNode);
072: this .validatorFactory = validatorFactory;
073: }
074:
075: public PrefsPreferenceSetImpl(Preferences prefsRootNode,
076: PreferenceSetComposite defaults)
077: throws BackingStoreException {
078: this (prefsRootNode);
079: this .defaults = defaults;
080: }
081:
082: /**
083: * <p>
084: * getNames
085: * </p>
086: *
087: * @see org.apache.jetspeed.om.common.preference.PreferenceSetComposite#getNames()
088: * @return
089: */
090: public Set getNames() {
091: try {
092: if (defaults != null) {
093: Set names = defaults.getNames();
094: names.addAll(new HashSet(Arrays.asList(prefsRootNode
095: .childrenNames())));
096: return names;
097: } else {
098: return new HashSet(Arrays.asList(prefsRootNode
099: .childrenNames()));
100: }
101: } catch (BackingStoreException e) {
102: String msg = "Preference backing store failed: "
103: + e.toString();
104: IllegalStateException ise = new IllegalStateException(msg);
105: ise.initCause(e);
106: throw ise;
107: }
108: }
109:
110: /**
111: * <p>
112: * get
113: * </p>
114: *
115: * @see org.apache.pluto.om.common.PreferenceSet#get(java.lang.String)
116: * @param arg0
117: * @return
118: */
119: public Preference get(String key) {
120: try {
121: Preference pref = null;
122: if (prefsRootNode.nodeExists(key)) {
123: pref = new PrefsPreference(prefsRootNode.node(key), key);
124: } else if (defaults != null) {
125: pref = defaults.get(key);
126: }
127:
128: return pref;
129: } catch (IllegalStateException ise) {
130: // node has been removed
131: return null;
132: } catch (BackingStoreException e) {
133: String msg = "Preference backing store failed: "
134: + e.toString();
135: IllegalStateException ise = new IllegalStateException(msg);
136: ise.initCause(e);
137: throw ise;
138: }
139: }
140:
141: /**
142: * <p>
143: * getPreferencesValidator
144: * </p>
145: *
146: * @see org.apache.pluto.om.common.PreferenceSet#getPreferencesValidator()
147: * @return
148: */
149: public PreferencesValidator getPreferencesValidator() {
150: if (validatorFactory != null) {
151: return validatorFactory.getPreferencesValidator();
152: }
153: return null;
154: }
155:
156: /**
157: * <p>
158: * add
159: * </p>
160: *
161: * @see org.apache.pluto.om.common.PreferenceSetCtrl#add(java.lang.String,
162: * java.util.List)
163: * @param name
164: * @param values
165: * @return
166: */
167: public Preference add(String name, List values) {
168: Iterator valuesItr = values.iterator();
169:
170: PrefsPreference pref = new PrefsPreference(prefsRootNode
171: .node(name), name);
172: while (valuesItr.hasNext()) {
173: pref.addValue((String) valuesItr.next());
174: }
175:
176: return pref;
177: }
178:
179: /**
180: * <p>
181: * remove
182: * </p>
183: *
184: * @see org.apache.pluto.om.common.PreferenceSetCtrl#remove(org.apache.pluto.om.common.Preference)
185: * @param arg0
186: */
187: public void remove(Preference pref) {
188: remove(pref.getName());
189: }
190:
191: /**
192: * <p>
193: * remove
194: * </p>
195: *
196: * @see org.apache.pluto.om.common.PreferenceSetCtrl#remove(java.lang.String)
197: * @param arg0
198: * @return
199: */
200: public Preference remove(String key) {
201: try {
202: Preferences nodeToRemove = prefsRootNode.node(key);
203:
204: if (nodeToRemove == null)
205: return null;
206: PrefsPreference pref = new PrefsPreference(nodeToRemove,
207: key);
208: nodeToRemove.removeNode();
209: return pref;
210: } catch (BackingStoreException e) {
211: String msg = "Preference backing store failed: "
212: + e.toString();
213: IllegalStateException ise = new IllegalStateException(msg);
214: ise.initCause(e);
215: throw ise;
216: }
217: }
218:
219: /**
220: *
221: */
222: public void flush() throws BackingStoreException {
223: prefsRootNode.flush();
224: }
225:
226: /**
227: *
228: * <p>
229: * clear
230: * </p>
231: *
232: * @throws BackingStoreException
233: */
234: public void clear() throws BackingStoreException {
235: prefsRootNode.removeNode();
236: }
237:
238: /**
239: * <p>
240: * size
241: * </p>
242: *
243: * @see org.apache.jetspeed.om.common.preference.PreferenceSetComposite#size()
244: * @return
245: */
246: public int size() {
247: try {
248: int length = prefsRootNode.childrenNames().length;
249:
250: if (defaults != null) {
251: length += defaults.size();
252: }
253:
254: return length;
255: } catch (IllegalStateException ise) {
256: // node has been removed
257: return 0;
258: } catch (BackingStoreException e) {
259: IllegalStateException ise = new IllegalStateException(e
260: .toString());
261: ise.initCause(e);
262: throw ise;
263: }
264: }
265:
266: /**
267: * <p>
268: * iterator
269: * </p>
270: *
271: * @see org.apache.pluto.om.common.PreferenceSet#iterator()
272: * @return
273: */
274: public Iterator iterator() {
275: return new PortletPrefsIterator();
276: }
277:
278: protected class PortletPrefsIterator implements Iterator {
279: int beginSize = 0;
280: int pointer;
281: String[] childrenNames;
282: protected PrefsPreference currentPref;
283:
284: protected PortletPrefsIterator() {
285: super ();
286: try {
287: childrenNames = prefsRootNode.childrenNames();
288: if (childrenNames != null)
289: beginSize = childrenNames.length;
290:
291: if (defaults != null) {
292: Vector v = new Vector();
293:
294: Iterator itr = defaults.getNames().iterator();
295: while (itr.hasNext()) {
296: String name = (String) itr.next();
297: if (!arrayContains(childrenNames, name)) {
298: v.add(name);
299: }
300: }
301: int j = v.size();
302: if (j > 0) {
303: int i = childrenNames.length;
304: String[] tempArray = new String[j + i];
305: System.arraycopy(childrenNames, 0, tempArray,
306: 0, i);
307: for (int x = 0; x < j; x++)
308: tempArray[i + x] = (String) v.get(x);
309: childrenNames = tempArray;
310: beginSize = i + j;
311: }
312: }
313: pointer = 0;
314: } catch (IllegalStateException ise) {
315: // node has been removed
316: childrenNames = new String[0];
317: } catch (BackingStoreException e) {
318: String msg = "Preference backing store failed: "
319: + e.toString();
320: IllegalStateException ise = new IllegalStateException(
321: msg);
322: ise.initCause(e);
323: throw ise;
324: }
325:
326: }
327:
328: /**
329: * <p>
330: * hasNext
331: * </p>
332: *
333: * @see java.util.Iterator#hasNext()
334: * @return
335: */
336: public boolean hasNext() {
337: try {
338: return pointer < beginSize;
339: } catch (Exception e) {
340: throw new ConcurrentModificationException(
341: "Underlying PreferenceSet has changed.");
342: }
343: }
344:
345: /**
346: * <p>
347: * next
348: * </p>
349: *
350: * @see java.util.Iterator#next()
351: * @return
352: */
353: public Object next() {
354: try {
355: currentPref = (PrefsPreference) get(childrenNames[pointer]);
356: pointer++;
357: return currentPref;
358: } catch (Exception e) {
359: throw new ConcurrentModificationException(
360: "Underlying PreferenceSet has changed.");
361: }
362: }
363:
364: /**
365: * <p>
366: * remove
367: * </p>
368: *
369: * @see java.util.Iterator#remove()
370: *
371: */
372: public void remove() {
373: if (currentPref == null) {
374: throw new IllegalStateException(
375: " next() must be called at least once before invoking remove().");
376: }
377:
378: PrefsPreferenceSetImpl.this .remove(currentPref);
379: beginSize--;
380:
381: }
382: }
383:
384: protected boolean arrayContains(String[] array, String value) {
385: for (int i = 0; i < array.length; i++) {
386: if (array[i].equals(value)) {
387: return true;
388: }
389: }
390:
391: return false;
392: }
393:
394: }
|