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.util.ArrayList;
20  import java.util.Collection;
21  import java.util.Iterator;
22  import java.util.Vector;
23  
24  import org.apache.jetspeed.cache.CacheElement;
25  import org.apache.jetspeed.cache.DistributedCacheObject;
26  import org.apache.jetspeed.cache.JetspeedCache;
27  import org.apache.jetspeed.components.dao.InitablePersistenceBrokerDaoSupport;
28  import org.apache.jetspeed.prefs.FailedToCreateNodeException;
29  import org.apache.jetspeed.prefs.NodeAlreadyExistsException;
30  import org.apache.jetspeed.prefs.NodeDoesNotExistException;
31  import org.apache.jetspeed.prefs.PreferencesProvider;
32  import org.apache.jetspeed.prefs.om.Node;
33  import org.apache.jetspeed.prefs.om.Property;
34  import org.apache.jetspeed.prefs.om.impl.NodeImpl;
35  import org.apache.jetspeed.prefs.om.impl.PropertyImpl;
36  import org.apache.ojb.broker.query.Criteria;
37  import org.apache.ojb.broker.query.Query;
38  import org.apache.ojb.broker.query.QueryFactory;
39  
40  /***
41   * <p>
42   * PersistenceBrokerPreferencesProvider
43   * </p>
44   * 
45   * @author <a href="mailto:weaver@apache.org">Scott T. Weaver </a>
46   * @version $Id: PersistenceBrokerPreferencesProvider.java 525266 2007-04-03 20:34:22Z taylor $
47   */
48  public class PersistenceBrokerPreferencesProvider extends InitablePersistenceBrokerDaoSupport implements
49          PreferencesProvider
50  {
51  
52      private static class NodeCache implements DistributedCacheObject
53      {
54          /*** The serial uid. */
55          private static final long serialVersionUID = 1853381807991868844L;
56          NodeImplProxy node = null;
57          String key = null;;
58          Collection children = null;;
59  
60          public NodeCache(NodeImplProxy node)
61          {
62              // System.out.println(this.getClass().getName() + "-" + "NodeCache (node)" + node.getFullPath());
63              this.node = node;
64              this.key = node.getFullPath() + "-" + node.getNodeType();
65          }
66  
67          public NodeCache(String fullpath, int type)
68          {
69              // System.out.println(this.getClass().getName() + "-" + "NodeCache - fullpath=" + fullpath);
70              this.key = fullpath + "-" + type;
71          }
72  
73          public boolean isChildrenLoaded()
74          {
75              // System.out.println(this.getClass().getName() + "-" + "isChildrenLoaded");
76              return children != null;
77          }
78  
79  
80  
81          public NodeImplProxy getNode()
82          {
83              // System.out.println(this.getClass().getName() + "-" + "getNode=" + node.getFullPath());
84              return node;
85          }
86  
87          public void setNode(NodeImplProxy node)
88          {
89              // System.out.println(this.getClass().getName() + "-" + "setFullpath=" + node.getFullPath());
90              this.node = node;
91          }
92  
93          public Collection getChildren()
94          {
95              // System.out.println(this.getClass().getName() + "-" + "getCHildren=" );
96              return children;
97          }
98  
99          public void setChildren(Collection children)
100         {
101             // System.out.println(this.getClass().getName() + "-" + "setChildren=" );
102             this.children = children;
103         }
104 
105         public boolean equals(Object obj)
106         {
107             if (obj != null && obj instanceof NodeCache)
108             {
109                 NodeCache other = (NodeCache) obj;
110                 return getKey().equals(other.getKey());
111             }
112             return false;
113         }
114 
115         public int hashCode()
116         {
117             return getKey().hashCode();
118         }
119         
120         public String getCacheKey()
121         {
122             return getKey();
123         }
124 
125 		public String getKey()
126 		{
127 			return key;
128 		}
129 
130 		
131 	    public void notifyChange(int action)
132 	    {
133 
134 	    	switch (action)
135 	    	{
136 	    		case CacheElement.ActionAdded:
137 //					System.out.println("CacheObject Added =" + this.getKey());
138 	    			break;
139 	    		case CacheElement.ActionChanged:
140 //					System.out.println("CacheObject Changed =" + this.getKey());
141 					if (this.node != null)
142 						this.node.invalidate();
143 	    			break;
144 	    		case CacheElement.ActionRemoved:
145 //					System.out.println("CacheObject Removed =" + this.getKey());
146 					if (this.node != null)
147 						this.node.invalidate();
148 	    			break;
149 	    		case CacheElement.ActionEvicted:
150 //					System.out.println("CacheObject Evicted =" + this.getKey());
151 					if (this.node != null)
152 						this.node.invalidate();
153 	    			break;
154 	    		case CacheElement.ActionExpired:
155 //					System.out.println("CacheObject Expired =" + this.getKey());
156 					if (this.node != null)
157 						this.node.invalidate();
158 	    			break;
159 	    		default:
160 					System.out.println("CacheObject - UNKOWN OPRERATION =" + this.getKey());
161 	    			return;
162 	    	}
163 	    	return;
164 		}
165     }
166 
167     private JetspeedCache preferenceCache;
168     
169     
170     /***
171      * @param repository
172      *            Location of repository mapping file. Must be available within the classpath.
173      * @param prefsFactoryImpl
174      *            <code>java.util.prefs.PreferencesFactory</code> implementation to use.
175      * @param enablePropertyManager
176      *            Whether or not we chould be suing the property manager.
177      * @throws ClassNotFoundException
178      *             if the <code>prefsFactoryImpl</code> argument does not reperesent a Class that exists in the
179      *             current classPath.
180      */
181     public PersistenceBrokerPreferencesProvider(String repositoryPath)
182             throws ClassNotFoundException
183     {
184         super(repositoryPath);
185         NodeImplProxy.setProvider(this);
186     }
187 
188     /***
189      * @param repository
190      *            Location of repository mapping file. Must be available within the classpath.
191      * @param prefsFactoryImpl
192      *            <code>java.util.prefs.PreferencesFactory</code> implementation to use.
193      * @param enablePropertyManager
194      *            Whether or not we chould be suing the property manager.
195      * @throws ClassNotFoundException
196      *             if the <code>prefsFactoryImpl</code> argument does not reperesent a Class that exists in the
197      *             current classPath.
198      */
199     public PersistenceBrokerPreferencesProvider(String repositoryPath, JetspeedCache preferenceCache)
200             throws ClassNotFoundException
201     {
202         this(repositoryPath);
203         this.preferenceCache = preferenceCache;
204     }
205 
206     protected void addToCache(NodeCache content)
207     {
208         CacheElement cachedElement = preferenceCache.createElement(content.getCacheKey(), content);
209         cachedElement.setTimeToIdleSeconds(preferenceCache.getTimeToIdleSeconds());
210         cachedElement.setTimeToLiveSeconds(preferenceCache.getTimeToLiveSeconds());
211         preferenceCache.put(cachedElement);        
212     }    
213   
214     private NodeCache getNode(String cacheKey)
215     {
216     	CacheElement cachedElement = preferenceCache.get(cacheKey);
217         if (cachedElement != null)
218          return (NodeCache)cachedElement.getContent();  
219         return null;
220     }
221 
222     
223     public Node getNode(String fullPath, int nodeType) throws NodeDoesNotExistException
224     {
225         NodeCache key = new NodeCache(fullPath, nodeType);
226         NodeCache hit = getNode(key.getCacheKey());
227         if (hit != null)
228         {
229             return hit.getNode();
230         }
231 
232         Criteria c = new Criteria();
233         c.addEqualTo("fullPath", fullPath);
234         c.addEqualTo("nodeType", new Integer(nodeType));
235         Query query = QueryFactory.newQuery(NodeImpl.class, c);
236 
237         Node nodeObj = (Node) getPersistenceBrokerTemplate().getObjectByQuery(query);
238         if (null != nodeObj)
239         {
240         	NodeImplProxy proxy = new NodeImplProxy(nodeObj);
241             addToCache(new NodeCache(proxy));
242             return proxy;
243            
244         }
245         else
246         {
247             throw new NodeDoesNotExistException("No node of type " + nodeType + "found at path: " + fullPath);
248         }
249     }
250     /***
251      * @see org.apache.jetspeed.prefs.PreferencesProvider#getNode(java.lang.String, int)
252      */
253     public void redoNode(NodeImplProxy proxy, String fullPath, int nodeType) throws NodeDoesNotExistException
254     {
255         
256         Criteria c = new Criteria();
257         c.addEqualTo("fullPath", fullPath);
258         c.addEqualTo("nodeType", new Integer(nodeType));
259         Query query = QueryFactory.newQuery(NodeImpl.class, c);
260 
261         Node nodeObj = (Node) getPersistenceBrokerTemplate().getObjectByQuery(query);
262         if (null != nodeObj)
263         {
264         	proxy.setNode(nodeObj);
265         	NodeCache cn = new NodeCache(nodeObj.getFullPath(), nodeObj.getNodeType());
266         	cn.setNode(proxy);
267             addToCache(cn);
268         }
269         else
270         {
271             throw new NodeDoesNotExistException("No node of type " + nodeType + "found at path: " + fullPath);
272         }
273     }
274 
275     /***
276      * @see org.apache.jetspeed.prefs.PreferencesProvider#nodeExists(java.lang.String, int)
277      */
278     public boolean nodeExists(String fullPath, int nodeType)
279     {
280         NodeCache key = new NodeCache(fullPath, nodeType);
281         if (preferenceCache.isKeyInCache(key))
282         	return true;
283         Criteria c = new Criteria();
284         c.addEqualTo("fullPath", fullPath);
285         c.addEqualTo("nodeType", new Integer(nodeType));
286         Query query = QueryFactory.newQuery(NodeImpl.class, c);
287 
288         Node nodeObj = (Node) getPersistenceBrokerTemplate().getObjectByQuery(query);
289         if (null != nodeObj)
290         {
291         	NodeImplProxy proxy = new NodeImplProxy(nodeObj);
292             addToCache(new NodeCache(proxy));
293             return true;
294         }
295         else
296         {
297             return false;
298         }
299     }
300 
301     /***
302      * @see org.apache.jetspeed.prefs.PreferencesProvider#createNode(org.apache.jetspeed.prefs.om.Node, java.lang.String, int, java.lang.String)
303      */
304     public Node createNode(Node parent, String nodeName, int nodeType, String fullPath)
305             throws FailedToCreateNodeException, NodeAlreadyExistsException
306     {
307         if (nodeExists(fullPath, nodeType))
308         {
309             throw new NodeAlreadyExistsException("Node of type " + nodeType + " already exists at path " + fullPath);
310         }
311         else
312         {
313             Long parentNodeId = null;
314             if (null != parent)
315             {
316                 parentNodeId = new Long(parent.getNodeId());
317             }
318 
319             Node nodeObj = new NodeImpl(parentNodeId, nodeName, nodeType, fullPath);
320 
321             try
322             {
323                 getPersistenceBrokerTemplate().store(nodeObj);
324             	NodeImplProxy proxy = new NodeImplProxy(nodeObj);
325                 addToCache(new NodeCache(proxy));
326                 return proxy;
327             }
328             catch (Exception e)
329             {
330                 throw new FailedToCreateNodeException("Failed to create node of type " + nodeType + " for the path "
331                         + fullPath + ".  " + e.toString(), e);
332             }
333 
334         }
335     }
336   
337     /***
338      * @see org.apache.jetspeed.prefs.PreferencesProvider#getChildren(org.apache.jetspeed.prefs.om.Node)
339      */
340     public Collection getChildren(Node parentNode)
341     {
342         NodeCache key = new NodeCache(parentNode.getFullPath(), parentNode.getNodeType());
343 
344         NodeCache hit = getNode(key.getCacheKey());
345         if (hit == null)
346         {
347         	NodeImplProxy proxy = new NodeImplProxy(parentNode);
348             hit = new NodeCache(proxy);
349             addToCache(hit);
350         }
351         if (hit.isChildrenLoaded())
352         {
353             return resolveChildren(hit.getChildren());
354         }
355 
356         Criteria c = new Criteria();
357         c.addEqualTo("parentNodeId", new Long(parentNode.getNodeId()));
358         Query query = QueryFactory.newQuery(NodeImpl.class, c);
359         Collection children = getPersistenceBrokerTemplate().getCollectionByQuery(query);
360         hit.setChildren(cacheChildren(children));
361         // null or not
362         return children;
363     }
364 
365     
366     private Collection resolveChildren(Collection children)
367     {
368     	if (children == null)
369     		return null;
370     	try
371     	{
372 	    	Iterator it = children.iterator();
373 	    	Vector v = new Vector();
374 	    	while (it.hasNext())
375 	    	{
376 	    		String s = (String) it.next();
377 	    		NodeCache hit =getNode(s);
378 	    		if (hit != null)
379 	    			v.add(hit.getNode());
380 	    	}
381 	    	return v;
382     	}
383     	catch (Exception e)
384     	{
385     		e.printStackTrace();
386     		return null;
387     	}
388     }
389 
390     
391     private Collection cacheChildren(Collection children)
392     {
393     	Iterator it = children.iterator();
394     	Vector v = new Vector();
395     	while (it.hasNext())
396     	{
397     		   Node key = (Node)it.next();	
398     	       NodeCache nodeKey = new NodeCache(key.getFullPath(),key.getNodeType());
399     	       NodeCache hit = getNode(nodeKey.getCacheKey());
400    	           if (hit == null)
401    	           {
402    	    		   NodeImplProxy proxy = new NodeImplProxy(key);
403    	    		   nodeKey.setNode(proxy);
404    	    	       addToCache(nodeKey);
405    	    	       hit= nodeKey;
406    	           }
407     	        v.add(hit.getCacheKey());
408     	}
409     	return v;
410     }
411 
412     /***
413      * @see org.apache.jetspeed.prefs.PreferencesProvider#storeNode(org.apache.jetspeed.prefs.om.Node)
414      */
415     public void storeNode(Node node)
416     {
417     	NodeImplProxy hit = null;
418     	if (node instanceof NodeImplProxy)
419     	{
420     		hit = (NodeImplProxy)node;
421     	}
422     	else
423     	{
424     		//System.out.println("WARNING!!!!STORE NODE!!!!!!!!!!!! -  Illegal Node element passed");
425     		hit = new NodeImplProxy(node);
426     	}
427     	
428         NodeCache key = new NodeCache(hit);
429         getPersistenceBrokerTemplate().store(hit.getNode()); // avoid racing condition with the db and with cluster notification
430         											// do the db first
431         preferenceCache.remove(key.getCacheKey()); // not sure we should actually do that, could also just update the node
432         addToCache(key);
433     }
434 
435     /***
436      * @see org.apache.jetspeed.prefs.PreferencesProvider#removeNode(org.apache.jetspeed.prefs.om.Node, org.apache.jetspeed.prefs.om.Node)
437      */
438     public void removeNode(Node parentNode, Node node)
439     {
440     	NodeImplProxy hit = null;
441     	NodeImplProxy parentHit = null;
442 
443     	if (node instanceof NodeImplProxy)
444     	{
445     		getPersistenceBrokerTemplate().delete(((NodeImplProxy)node).getNode());  //avoid race conditions - do this first    
446     	}
447     	else
448     		getPersistenceBrokerTemplate().delete(node);  //avoid race conditions - do this first    
449     		
450     	if (node instanceof NodeImplProxy)
451     	{
452     		hit = (NodeImplProxy)node;
453     	}
454     	else
455     	{
456     		//System.out.println("WARNING!!!!REMOVE NODE!!!!!!!!!!!! -  Illegal Node element passed");
457     		hit = new NodeImplProxy(node);
458     	}
459         NodeCache key = new NodeCache(hit);
460         preferenceCache.remove(key.getCacheKey());
461         if ( parentNode != null )
462         {
463         	if (parentNode instanceof NodeImplProxy)
464         	{
465         		parentHit = (NodeImplProxy)parentNode;
466         	}
467         	else
468         	{
469         		//System.out.println("WARNING!!!!REMOVE NODE!!!!!!!!!!!! -  Illegal Node element passed");
470         		parentHit = new NodeImplProxy(parentNode);
471         	}
472         	NodeCache parentKey = new NodeCache(parentHit);
473         	parentKey = getNode(parentKey.getCacheKey());
474             if ( parentKey != null && parentKey.isChildrenLoaded() )
475             {
476             	parentKey.getChildren().remove(key.getCacheKey());
477             }
478         }
479     }
480     
481     /***
482      * @see org.apache.jetspeed.prefs.PreferencesProvider#lookupPreference(java.lang.String, java.lang.String, java.lang.String)
483      */
484     public Collection lookupPreference(String nodeName, String propertyName, String propertyValue)
485     {
486         Criteria c = new Criteria();
487         if (nodeName != null)
488         {
489             c.addEqualTo("nodeName", nodeName);
490         }
491         if (propertyName != null)
492         {
493             c.addEqualTo("nodeProperties.propertyName", propertyName);
494         }
495         if (propertyValue != null)
496         {
497             c.addEqualTo("nodeProperties.propertyValue", propertyValue);
498         }
499         Query query = QueryFactory.newQuery(NodeImpl.class, c);
500         Collection children = getPersistenceBrokerTemplate().getCollectionByQuery(query);
501         Collection proxied = new ArrayList();
502         Iterator iter = children.iterator();
503         while (iter.hasNext())
504         {
505             NodeImpl node = (NodeImpl)iter.next();              
506             NodeCache key = new NodeCache(node.getFullPath(), node.getNodeType());
507             NodeCache hit = getNode(key.getCacheKey());
508             if (hit == null)
509             {
510                 NodeImplProxy proxy = new NodeImplProxy(node);
511                 addToCache(new NodeCache(proxy));
512                 proxied.add(proxy);
513             }            
514             else
515             {
516                 proxied.add(hit.getNode());
517             }
518         }
519         return proxied;       
520     }
521     
522     public Property createProperty(Node node, String name, Object value)
523     {
524         return new PropertyImpl(node.getNodeId(), name, value);
525     }
526     
527 }