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.prefs.impl;
018:
019: import java.sql.Timestamp;
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.Iterator;
023: import java.util.prefs.AbstractPreferences;
024: import java.util.prefs.BackingStoreException;
025: import java.util.prefs.Preferences;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.apache.jetspeed.prefs.FailedToCreateNodeException;
030: import org.apache.jetspeed.prefs.NodeAlreadyExistsException;
031: import org.apache.jetspeed.prefs.NodeDoesNotExistException;
032: import org.apache.jetspeed.prefs.PreferencesProvider;
033: import org.apache.jetspeed.prefs.om.Node;
034: import org.apache.jetspeed.prefs.om.Property;
035: import org.apache.jetspeed.prefs.om.impl.PropertyImpl;
036:
037: /**
038: * <p>
039: * S {@link Preferences}implementation relying on Jetspeed OJB based
040: * persistence plugin.
041: * </p>
042: *
043: * @author <a href="mailto:dlestrat@apache.org">David Le Strat </a>
044: */
045: public class PreferencesImpl extends AbstractPreferences {
046:
047: /** User <tt>Preferences<tt> node type. */
048: public static final int USER_NODE_TYPE = 0;
049:
050: /** System <tt>Preferences</tt> node type. */
051: public static final int SYSTEM_NODE_TYPE = 1;
052:
053: /** The current <code>Node</code> object. */
054: private Node node = null;
055:
056: /** Logger. */
057: private static final Log log = LogFactory
058: .getLog(PreferencesImpl.class);
059:
060: protected static PreferencesProvider prefsProvider;
061:
062: static PreferencesImpl systemRoot;
063:
064: static PreferencesImpl userRoot;
065:
066: /**
067: * <p>
068: * Constructs a root node in the underlying datastore if they have not yet
069: * been created.
070: * </p>
071: * <p>
072: * Logs a warning if the underlying datastore is unavailable.
073: * </p>
074: *
075: * @param parent The parent object.
076: * @param nodeName The node name.
077: * @param nodeType The node type.
078: */
079: public PreferencesImpl(PreferencesImpl parent, String nodeName,
080: int nodeType) throws IllegalStateException {
081: super (parent, nodeName);
082:
083: try {
084: if (parent != null) {
085: this .node = prefsProvider.createNode(parent.getNode(),
086: nodeName, nodeType, this .absolutePath());
087: } else {
088: this .node = prefsProvider.createNode(null, nodeName,
089: nodeType, this .absolutePath());
090: }
091:
092: newNode = true;
093: } catch (FailedToCreateNodeException e) {
094: IllegalStateException ise = new IllegalStateException(
095: "Failed to create new Preferences of type "
096: + nodeType + " for path "
097: + this .absolutePath());
098: ise.initCause(e);
099: throw ise;
100: } catch (NodeAlreadyExistsException e) {
101: try {
102: node = prefsProvider.getNode(this .absolutePath(),
103: nodeType);
104: newNode = false;
105: } catch (NodeDoesNotExistException e1) {
106: // If we get this at this point something is very wrong
107: IllegalStateException ise = new IllegalStateException(
108: "Unable to create node for Preferences of type "
109: + nodeType
110: + " for path "
111: + this .absolutePath()
112: + ". If you see this exception at this, it more than likely means that the Preferences backing store is corrupt.");
113: ise.initCause(e1);
114: throw ise;
115: }
116: }
117:
118: }
119:
120: /**
121: * @see java.util.prefs.Preferences#childrenNamesSpi()
122: */
123: public String[] childrenNamesSpi() throws BackingStoreException {
124: Collection nodes = prefsProvider.getChildren(getNode());
125:
126: if (null != nodes) {
127: ArrayList childrenNames = new ArrayList(nodes.size());
128: for (Iterator i = nodes.iterator(); i.hasNext();) {
129: Node curnode = (Node) i.next();
130: childrenNames.add(curnode.getNodeName());
131: }
132: return (String[]) childrenNames.toArray(new String[0]);
133: } else {
134: // The returned array is of size zero if this node has no
135: // preferences.
136: return new String[0];
137: }
138: }
139:
140: /**
141: * @see java.util.prefs.Preferences#childSpi(java.lang.String)
142: */
143: public AbstractPreferences childSpi(String name) {
144: return new PreferencesImpl(this , name, node.getNodeType());
145: }
146:
147: /**
148: * @see java.util.prefs.Preferences#flushSpi()
149: */
150: public void flushSpi() throws BackingStoreException {
151: prefsProvider.storeNode(this .node);
152: }
153:
154: /**
155: * @see java.util.prefs.Preferences#getSpi(java.lang.String)
156: */
157: public String getSpi(String key) {
158: String value = null;
159: Collection properties = node.getNodeProperties();
160:
161: for (Iterator i = properties.iterator(); i.hasNext();) {
162: Property curProp = (Property) i.next();
163: if ((null != curProp)
164: && (null != curProp.getPropertyName())
165: && (curProp.getPropertyName().equals(key))) {
166: value = curProp.getPropertyValue();
167: }
168: }
169: return value;
170: }
171:
172: /**
173: * @see java.util.prefs.Preferences#keysSpi()
174: */
175: public String[] keysSpi() {
176: ArrayList propertyNames = new ArrayList();
177:
178: Collection propCol = node.getNodeProperties();
179: if ((null != propCol) && propCol.size() > 0) {
180: for (Iterator j = propCol.iterator(); j.hasNext();) {
181: Property curprop = (Property) j.next();
182: if ((null != curprop)
183: && (null != curprop.getPropertyName())
184: && !propertyNames.contains(curprop
185: .getPropertyName())) {
186: propertyNames.add(curprop.getPropertyName());
187: }
188: }
189: }
190:
191: return (String[]) propertyNames
192: .toArray(new String[propertyNames.size()]);
193: }
194:
195: /**
196: * @see java.util.prefs.Preferences#putSpi(java.lang.String,
197: * java.lang.String)
198: */
199: public void putSpi(String key, String value) {
200: Collection properties = node.getNodeProperties();
201: if (null == properties) {
202: log.error("Could not retrieve node property: [key: " + key
203: + ", value:" + value + "]");
204: return;
205: }
206:
207: // If the property exists, update its value.
208: boolean propFound = false;
209: for (Iterator i = properties.iterator(); i.hasNext();) {
210: Property curProp = (Property) i.next();
211: if ((null != curProp)
212: && (null != curProp.getPropertyName())
213: && curProp.getPropertyName().equals(key)) {
214: propFound = true;
215: curProp.setPropertyValue(value);
216: curProp.setModifiedDate(new Timestamp(System
217: .currentTimeMillis()));
218: if (log.isDebugEnabled()) {
219: log.debug("Update existing property: "
220: + curProp.toString());
221: }
222: // Property found, we break.
223: break;
224: }
225: }
226: if (!propFound) {
227: properties.add(new PropertyImpl(node.getNodeId(), key,
228: value));
229: }
230:
231: prefsProvider.storeNode(node);
232: }
233:
234: /**
235: * @see java.util.prefs.Preferences#removeNodeSpi()
236: */
237: public void removeNodeSpi() throws BackingStoreException {
238: Node parentNode = null;
239: Preferences parent = parent();
240: if (parent != null && parent instanceof PreferencesImpl) {
241: parentNode = ((PreferencesImpl) parent).getNode();
242: }
243: prefsProvider.removeNode(parentNode, node);
244: }
245:
246: /**
247: * @see java.util.prefs.Preferences#removeSpi(java.lang.String)
248: */
249: public void removeSpi(String key) {
250: Collection properties = node.getNodeProperties();
251:
252: for (Iterator i = properties.iterator(); i.hasNext();) {
253: Property curProp = (Property) i.next();
254:
255: if ((curProp.getPropertyName().equals(key))) {
256: i.remove();
257: }
258: }
259: // Update node.
260: prefsProvider.storeNode(node);
261: }
262:
263: /**
264: * @see java.util.prefs.Preferences#syncSpi()
265: */
266: public void syncSpi() throws BackingStoreException {
267: flushSpi();
268: }
269:
270: /**
271: *
272: * <p>
273: * getNode
274: * </p>
275: *
276: * @return
277: */
278: public Node getNode() {
279: return node;
280: }
281:
282: /**
283: *
284: * <p>
285: * setPreferencesProvider
286: * </p>
287: * Sets the <code>org.apache.jetspeed.prefs.PreferencesProvider</code>
288: * that will support backing store operations for all
289: * <code>PreferencesImpls</code>
290: *
291: * @param prefsProvider
292: */
293: public static void setPreferencesProvider(
294: PreferencesProvider prefsProvider) {
295: PreferencesImpl.prefsProvider = prefsProvider;
296: }
297: }
|