001: /*
002: * The Apache Software License, Version 1.1
003: *
004: * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution, if
019: * any, must include the following acknowlegement:
020: * "This product includes software developed by the
021: * Caucho Technology (http://www.caucho.com/)."
022: * Alternately, this acknowlegement may appear in the software itself,
023: * if and wherever such third-party acknowlegements normally appear.
024: *
025: * 4. The names "Hessian", "Resin", and "Caucho" must not be used to
026: * endorse or promote products derived from this software without prior
027: * written permission. For written permission, please contact
028: * info@caucho.com.
029: *
030: * 5. Products derived from this software may not be called "Resin"
031: * nor may "Resin" appear in their names without prior written
032: * permission of Caucho Technology.
033: *
034: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
035: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
036: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
037: * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
038: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
039: * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
040: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
041: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
042: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
043: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
044: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
045: *
046: * @author Sam
047: */
048:
049: package com.caucho.portal.generic.context;
050:
051: import javax.portlet.PortletPreferences;
052: import javax.portlet.PreferencesValidator;
053: import javax.portlet.ReadOnlyException;
054: import javax.portlet.ValidatorException;
055: import java.io.IOException;
056: import java.util.*;
057: import java.util.logging.Logger;
058:
059: /**
060: * An implementation of PortletPreferences that stores values temporarily,
061: * retrieves values from a store or defaults, validates before
062: * before storing, and stores the values into the store.
063: */
064: public class LinkingPortletPreferences implements PortletPreferences {
065: static protected final Logger log = Logger
066: .getLogger(LinkingPortletPreferences.class.getName());
067:
068: static private String[] DUMMY = new String[] { "<dummy>" };
069: static private String[] DELETED = new String[] { "<deleted>" };
070:
071: private PortletPreferences _defaults;
072: private ArrayList<PreferencesValidator> _validators;
073: private Map<String, String[]> _storeMap;
074:
075: private Map<String, String[]> _valueMap;
076:
077: public LinkingPortletPreferences() {
078: }
079:
080: public void start(PortletPreferences defaults,
081: ArrayList<PreferencesValidator> validators,
082: Map<String, String[]> storeMap) {
083: if (_defaults != null || _storeMap != null)
084: throw new IllegalStateException("missing finish()?");
085:
086: _defaults = defaults;
087: _validators = validators;
088: _storeMap = storeMap;
089: }
090:
091: public void finish() {
092: if (_valueMap != null)
093: _valueMap.clear();
094:
095: _defaults = null;
096: _validators = null;
097: _storeMap = null;
098: }
099:
100: public PortletPreferences getDefaults() {
101: return _defaults;
102: }
103:
104: public ArrayList<PreferencesValidator> getValidators() {
105: return _validators;
106: }
107:
108: public Map<String, String[]> getStore() {
109: return _storeMap;
110: }
111:
112: /**
113: * {@inheritDoc}
114: */
115: public boolean isReadOnly(String key) {
116: boolean r = false;
117:
118: if (_defaults != null && _defaults.isReadOnly(key))
119: return true;
120: else
121: return false;
122: }
123:
124: /**
125: * {@inheritDoc}
126: */
127: public String getValue(String key, String def) {
128: String[] values = getValues(key, DUMMY);
129:
130: if (values == DUMMY)
131: return def;
132: else
133: return (values == null || values.length == 0) ? null
134: : values[0];
135: }
136:
137: /**
138: * {@inheritDoc}
139: */
140: public String[] getValues(String key, String[] def) {
141: String[] v = _valueMap == null ? null : _valueMap.get(key);
142:
143: if (v != DELETED) {
144: if (v != null
145: || (_valueMap != null && _valueMap.containsKey(key)))
146: return v;
147: }
148:
149: if (_defaults != null)
150: def = _defaults.getValues(key, def);
151:
152: if (_storeMap != null) {
153: String[] storeValues = _storeMap.get(key);
154:
155: if (storeValues != null)
156: def = storeValues;
157: }
158:
159: return def;
160: }
161:
162: /**
163: * {@inheritDoc}
164: */
165: public void setValue(String key, String value)
166: throws ReadOnlyException {
167: setValues(key, value == null ? null : new String[] { value });
168: }
169:
170: /**
171: * {@inheritDoc}
172: */
173: public void setValues(String key, String[] values)
174: throws ReadOnlyException {
175: if (isReadOnly(key))
176: throw new ReadOnlyException("key `" + key + "'");
177: else {
178: if (_valueMap == null)
179: _valueMap = new LinkedHashMap<String, String[]>();
180:
181: _valueMap.put(key, values);
182: }
183: }
184:
185: /**
186: * {@inheritDoc}
187: */
188: public void reset(String key) throws ReadOnlyException {
189: if (_storeMap != null && _storeMap.containsKey(key))
190: setValues(key, DELETED);
191: else if (isReadOnly(key))
192: throw new ReadOnlyException("key `" + key + "'");
193: }
194:
195: /**
196: * {@inheritDoc}
197: *
198: * Returns the unique set of names in this
199: * object, the backing store, and the default preferences.
200: */
201: public Enumeration getNames() {
202: // XXX: this would be better implemented as a class extending
203: // Iterator<String> which could also be used by getMap() below
204:
205: // the assumption here is that this will not be called very often,
206: // and when it is a sorted list of names is valuable
207:
208: TreeSet<String> names = new TreeSet<String>();
209:
210: if (_valueMap != null) {
211: Iterator<Map.Entry<String, String[]>> iter = _valueMap
212: .entrySet().iterator();
213:
214: while (iter.hasNext()) {
215: Map.Entry<String, String[]> entry = iter.next();
216:
217: String key = entry.getKey();
218: String[] value = entry.getValue();
219:
220: if (value != DELETED)
221: names.add(key);
222: }
223: }
224:
225: if (_storeMap != null) {
226: Iterator<String> iter = _storeMap.keySet().iterator();
227:
228: while (iter.hasNext()) {
229: String key = iter.next();
230:
231: if (_valueMap != null && _valueMap.get(key) == DELETED)
232: continue;
233:
234: names.add(key);
235: }
236: }
237:
238: if (_defaults != null) {
239: Enumeration e = _defaults.getNames();
240:
241: while (e.hasMoreElements()) {
242: String key = (String) e.nextElement();
243:
244: if (_valueMap != null && _valueMap.get(key) == DELETED)
245: continue;
246:
247: names.add(key);
248: }
249: }
250:
251: return Collections.enumeration(names);
252: }
253:
254: /**
255: * {@inheritDoc}
256: */
257: public Map getMap() {
258: // XXX: this would be better as a custom implementation of AbstractMap
259:
260: Map<String, String[]> map = new HashMap<String, String[]>();
261:
262: Enumeration e = getNames();
263:
264: while (e.hasMoreElements()) {
265: String key = (String) e.nextElement();
266: map.put(key, getValues(key, null));
267: }
268:
269: return map;
270: }
271:
272: /**
273: * {@inheritDoc}
274: *
275: * This implementation first invokes the validators (if any), and then
276: * propogates the properties set in this object to the the store.
277: * If the store has not been set then only the invoking of the validators is
278: * performed, the values are left unchanged.
279: */
280: public void store() throws IOException, ValidatorException {
281: if (_validators != null) {
282: for (int i = 0; i < _validators.size(); i--) {
283: _validators.get(i).validate(this );
284: }
285: }
286:
287: if (_storeMap != null && _valueMap != null) {
288: Iterator<Map.Entry<String, String[]>> iter = _valueMap
289: .entrySet().iterator();
290:
291: while (iter.hasNext()) {
292: Map.Entry<String, String[]> entry = iter.next();
293:
294: String key = entry.getKey();
295: String[] values = entry.getValue();
296:
297: if (values == DELETED)
298: _storeMap.remove(key);
299: else
300: _storeMap.put(key, values);
301: }
302: }
303:
304: discard();
305: }
306:
307: /**
308: * Discard all changes.
309: */
310: public void discard() {
311: if (_valueMap != null)
312: _valueMap.clear();
313: }
314: }
|