View Javadoc

1   /* 
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.prefs.impl;
18  
19  import java.sql.Timestamp;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.Iterator;
23  import java.util.prefs.AbstractPreferences;
24  import java.util.prefs.BackingStoreException;
25  import java.util.prefs.Preferences;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.jetspeed.prefs.FailedToCreateNodeException;
30  import org.apache.jetspeed.prefs.NodeAlreadyExistsException;
31  import org.apache.jetspeed.prefs.NodeDoesNotExistException;
32  import org.apache.jetspeed.prefs.PreferencesProvider;
33  import org.apache.jetspeed.prefs.om.Node;
34  import org.apache.jetspeed.prefs.om.Property;
35  import org.apache.jetspeed.prefs.om.impl.PropertyImpl;
36  
37  /***
38   * <p>
39   * S {@link Preferences}implementation relying on Jetspeed OJB based
40   * persistence plugin.
41   * </p>
42   * 
43   * @author <a href="mailto:dlestrat@apache.org">David Le Strat </a>
44   */
45  public class PreferencesImpl extends AbstractPreferences
46  {
47  
48      /*** User <tt>Preferences<tt> node type. */
49      public static final int USER_NODE_TYPE = 0;
50  
51      /*** System <tt>Preferences</tt> node type. */
52      public static final int SYSTEM_NODE_TYPE = 1;
53  
54      /*** The current <code>Node</code> object. */
55      private Node node = null;
56  
57      /*** Logger. */
58      private static final Log log = LogFactory.getLog(PreferencesImpl.class);
59  
60      protected static PreferencesProvider prefsProvider;
61  
62      static PreferencesImpl systemRoot;
63  
64      static PreferencesImpl userRoot;
65  
66      /***
67       * <p>
68       * Constructs a root node in the underlying datastore if they have not yet
69       * been created.
70       * </p>
71       * <p>
72       * Logs a warning if the underlying datastore is unavailable.
73       * </p>
74       * 
75       * @param parent The parent object.
76       * @param nodeName The node name.
77       * @param nodeType The node type.
78       */
79      public PreferencesImpl(PreferencesImpl parent, String nodeName, int nodeType) throws IllegalStateException
80      {
81          super(parent, nodeName);
82  
83          try
84          {
85              if (parent != null)
86              {
87                  this.node = prefsProvider.createNode(parent.getNode(), nodeName, nodeType, this.absolutePath());
88              }
89              else
90              {
91                  this.node = prefsProvider.createNode(null, nodeName, nodeType, this.absolutePath());
92              }
93  
94              newNode = true;
95          }
96          catch (FailedToCreateNodeException e)
97          {
98              IllegalStateException ise = new IllegalStateException("Failed to create new Preferences of type "
99                      + nodeType + " for path " + this.absolutePath());
100             ise.initCause(e);
101             throw ise;
102         }
103         catch (NodeAlreadyExistsException e)
104         {
105             try
106             {
107                 node = prefsProvider.getNode(this.absolutePath(), nodeType);
108                 newNode = false;
109             }
110             catch (NodeDoesNotExistException e1)
111             {
112                 // If we get this at this point something is very wrong
113                 IllegalStateException ise = new IllegalStateException(
114                         "Unable to create node for Preferences of type "
115                                 + nodeType
116                                 + " for path "
117                                 + this.absolutePath()
118                                 + ".  If you see this exception at this, it more than likely means that the Preferences backing store is corrupt.");
119                 ise.initCause(e1);
120                 throw ise;
121             }
122         }
123 
124     }
125 
126     /***
127      * @see java.util.prefs.Preferences#childrenNamesSpi()
128      */
129     public String[] childrenNamesSpi() throws BackingStoreException
130     {
131         Collection nodes = prefsProvider.getChildren(getNode());
132 
133         if (null != nodes)
134         {
135             ArrayList childrenNames = new ArrayList(nodes.size());
136             for (Iterator i = nodes.iterator(); i.hasNext();)
137             {
138                 Node curnode = (Node) i.next();
139                 childrenNames.add(curnode.getNodeName());
140             }
141             return (String[]) childrenNames.toArray(new String[0]);
142         }
143         else
144         {
145             // The returned array is of size zero if this node has no
146             // preferences.
147             return new String[0];
148         }
149     }
150 
151     /***
152      * @see java.util.prefs.Preferences#childSpi(java.lang.String)
153      */
154     public AbstractPreferences childSpi(String name)
155     {
156         return new PreferencesImpl(this, name, node.getNodeType());
157     }
158 
159     /***
160      * @see java.util.prefs.Preferences#flushSpi()
161      */
162     public void flushSpi() throws BackingStoreException
163     {
164         prefsProvider.storeNode(this.node);
165     }
166 
167     /***
168      * @see java.util.prefs.Preferences#getSpi(java.lang.String)
169      */
170     public String getSpi(String key)
171     {
172         String value = null;
173         Collection properties = node.getNodeProperties();
174 
175         for (Iterator i = properties.iterator(); i.hasNext();)
176         {
177             Property curProp = (Property) i.next();
178             if ((null != curProp) && (null != curProp.getPropertyName()) && (curProp.getPropertyName().equals(key)))
179             {
180                 value = curProp.getPropertyValue();
181             }
182         }
183         return value;
184     }
185 
186     /***
187      * @see java.util.prefs.Preferences#keysSpi()
188      */
189     public String[] keysSpi()
190     {
191         ArrayList propertyNames = new ArrayList();
192 
193         Collection propCol = node.getNodeProperties();
194         if ((null != propCol) && propCol.size() > 0)
195         {
196             for (Iterator j = propCol.iterator(); j.hasNext();)
197             {
198                 Property curprop = (Property) j.next();
199                 if ((null != curprop) && (null != curprop.getPropertyName())
200                         && !propertyNames.contains(curprop.getPropertyName()))
201                 {
202                     propertyNames.add(curprop.getPropertyName());
203                 }
204             }
205         }
206 
207         return (String[]) propertyNames.toArray(new String[propertyNames.size()]);
208     }
209 
210     /***
211      * @see java.util.prefs.Preferences#putSpi(java.lang.String,
212      *      java.lang.String)
213      */
214     public void putSpi(String key, String value)
215     {
216         Collection properties = node.getNodeProperties();
217         if (null == properties)
218         {
219             log.error("Could not retrieve node property: [key: " + key + ", value:" + value + "]");
220             return;
221         }
222 
223         // If the property exists, update its value.
224         boolean propFound = false;
225         for (Iterator i = properties.iterator(); i.hasNext();)
226         {
227             Property curProp = (Property) i.next();
228             if ((null != curProp) && (null != curProp.getPropertyName()) && curProp.getPropertyName().equals(key))
229             {
230                 propFound = true;
231                 curProp.setPropertyValue(value);
232                 curProp.setModifiedDate(new Timestamp(System.currentTimeMillis()));
233                 if (log.isDebugEnabled())
234                 {
235                     log.debug("Update existing property: " + curProp.toString());
236                 }
237                 // Property found, we break.
238                 break;
239             }
240         }
241         if (!propFound)
242         {
243             properties.add(new PropertyImpl(node.getNodeId(), key, value));
244         }
245 
246         prefsProvider.storeNode(node);
247     }
248 
249     /***
250      * @see java.util.prefs.Preferences#removeNodeSpi()
251      */
252     public void removeNodeSpi() throws BackingStoreException
253     {
254         Node parentNode = null;
255         Preferences parent = parent();
256         if (parent != null && parent instanceof PreferencesImpl)
257         {
258             parentNode = ((PreferencesImpl) parent).getNode();
259         }
260         prefsProvider.removeNode(parentNode, node);
261     }
262 
263     /***
264      * @see java.util.prefs.Preferences#removeSpi(java.lang.String)
265      */
266     public void removeSpi(String key)
267     {
268         Collection properties = node.getNodeProperties();
269 
270         for (Iterator i = properties.iterator(); i.hasNext();)
271         {
272             Property curProp = (Property) i.next();
273 
274             if ((curProp.getPropertyName().equals(key)))
275             {
276                 i.remove();
277             }
278         }
279         // Update node.
280         prefsProvider.storeNode(node);
281     }
282 
283     /***
284      * @see java.util.prefs.Preferences#syncSpi()
285      */
286     public void syncSpi() throws BackingStoreException
287     {
288         flushSpi();
289     }
290 
291     /***
292      * 
293      * <p>
294      * getNode
295      * </p>
296      * 
297      * @return
298      */
299     public Node getNode()
300     {
301         return node;
302     }
303 
304     /***
305      * 
306      * <p>
307      * setPreferencesProvider
308      * </p>
309      * Sets the <code>org.apache.jetspeed.prefs.PreferencesProvider</code>
310      * that will support backing store operations for all
311      * <code>PreferencesImpls</code>
312      * 
313      * @param prefsProvider
314      */
315     public static void setPreferencesProvider(PreferencesProvider prefsProvider)
316     {
317         PreferencesImpl.prefsProvider = prefsProvider;
318     }
319 }