KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > policy > CachedPolicyFactory


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.policy;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.concurrent.locks.ReentrantReadWriteLock JavaDoc;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28
29 /**
30  * Policy Factory with caching support.
31  *
32  * @author David Caruana
33  *
34  * @param <B> the type of Binding
35  * @param <P> the type of Policy
36  */

37 /*package*/ class CachedPolicyFactory<B extends BehaviourBinding, P extends Policy> extends PolicyFactory<B, P>
38 {
39     // Logger
40
private static final Log logger = LogFactory.getLog(PolicyComponentImpl.class);
41
42     // Behaviour Filter
43
private BehaviourFilter behaviourFilter = null;
44     
45     // Cache Lock
46
private ReentrantReadWriteLock JavaDoc lock = new ReentrantReadWriteLock JavaDoc();
47
48     /**
49      * Cache for a single Policy interface (keyed by Binding)
50      */

51     private Map JavaDoc<B, P> singleCache = new HashMap JavaDoc<B, P>();
52     
53     /**
54      * Cache for a collection of Policy interfaces (keyed by Binding)
55      */

56     private Map JavaDoc<B, Collection JavaDoc<P>> listCache = new HashMap JavaDoc<B, Collection JavaDoc<P>>();
57
58     
59     /**
60      * Construct cached policy factory
61      *
62      * @param policyClass the policy interface class
63      * @param index the behaviour index to search on
64      */

65     /*package*/ CachedPolicyFactory(Class JavaDoc<P> policyClass, BehaviourIndex<B> index)
66     {
67         super(policyClass, index);
68         behaviourFilter = index.getFilter();
69
70         // Register this cached policy factory as a change observer of the behaviour index
71
// to allow for cache to be cleared appropriately.
72
index.addChangeObserver(new BehaviourChangeObserver<B>()
73         {
74             public void addition(B binding, Behaviour behaviour)
75             {
76                 clearCache("aggregate delegate", singleCache, binding);
77                 clearCache("delegate collection", listCache, binding);
78             }
79         });
80     }
81
82
83     @Override JavaDoc
84     public P create(B binding)
85     {
86         // When behaviour filters are activated bypass the cache
87
if (behaviourFilter != null && behaviourFilter.isActivated())
88         {
89             return super.create(binding);
90         }
91         
92         lock.readLock().lock();
93
94         try
95         {
96             P policyInterface = singleCache.get(binding);
97             if (policyInterface == null)
98             {
99                 // Upgrade read lock to write lock
100
lock.readLock().unlock();
101                 lock.writeLock().lock();
102
103                 try
104                 {
105                     // Check again
106
policyInterface = singleCache.get(binding);
107                     if (policyInterface == null)
108                     {
109                         policyInterface = super.create(binding);
110                         singleCache.put(binding, policyInterface);
111                         
112                         if (logger.isDebugEnabled())
113                             logger.debug("Cached delegate interface " + policyInterface + " for " + binding + " and policy " + getPolicyClass());
114                     }
115                 }
116                 finally
117                 {
118                     // Downgrade lock to read
119
lock.readLock().lock();
120                     lock.writeLock().unlock();
121                 }
122             }
123             return policyInterface;
124         }
125         finally
126         {
127             lock.readLock().unlock();
128         }
129     }
130     
131
132     @Override JavaDoc
133     public Collection JavaDoc<P> createList(B binding)
134     {
135         // When behaviour filters are activated bypass the cache
136
if (behaviourFilter != null && behaviourFilter.isActivated())
137         {
138             return super.createList(binding);
139         }
140         
141         lock.readLock().lock();
142
143         try
144         {
145             Collection JavaDoc<P> policyInterfaces = listCache.get(binding);
146             if (policyInterfaces == null)
147             {
148                 // Upgrade read lock to write lock
149
lock.readLock().unlock();
150                 lock.writeLock().lock();
151
152                 try
153                 {
154                     // Check again
155
policyInterfaces = listCache.get(binding);
156                     if (policyInterfaces == null)
157                     {
158                         policyInterfaces = super.createList(binding);
159                         listCache.put(binding, policyInterfaces);
160                 
161                         if (logger.isDebugEnabled())
162                             logger.debug("Cached delegate interface collection " + policyInterfaces + " for " + binding + " and policy " + getPolicyClass());
163                     }
164                 }
165                 finally
166                 {
167                     // Downgrade lock to read
168
lock.readLock().lock();
169                     lock.writeLock().unlock();
170                 }
171             }
172             return policyInterfaces;
173         }
174         finally
175         {
176             lock.readLock().unlock();
177         }
178     }
179     
180     
181     /**
182      * Clear entries in the cache based on binding changes.
183      *
184      * @param cacheDescription description of cache to clear
185      * @param cache the cache to clear
186      * @param binding the binding
187      */

188     private void clearCache(String JavaDoc cacheDescription, Map JavaDoc<B, ?> cache, B binding)
189     {
190         if (binding == null)
191         {
192             lock.writeLock().lock();
193
194             try
195             {
196                 // A specific binding has not been provided, so clear all entries
197
cache.clear();
198                 
199                 if (logger.isDebugEnabled() && cache.isEmpty() == false)
200                     logger.debug("Cleared " + cacheDescription + " cache (all class bindings) for policy " + getPolicyClass());
201             }
202             finally
203             {
204                 lock.writeLock().unlock();
205             }
206         }
207         else
208         {
209             // A specific binding has been provided. Build a list of entries
210
// that require removal. An entry is removed if the binding in the
211
// list is equal or derived from the changed binding.
212
Collection JavaDoc<B> invalidBindings = new ArrayList JavaDoc<B>();
213             for (B cachedBinding : cache.keySet())
214             {
215                 // Determine if binding is equal or derived from changed binding
216
BehaviourBinding generalisedBinding = cachedBinding;
217                 while(generalisedBinding != null)
218                 {
219                     if (generalisedBinding.equals(binding))
220                     {
221                         invalidBindings.add(cachedBinding);
222                         break;
223                     }
224                     generalisedBinding = generalisedBinding.generaliseBinding();
225                 }
226             }
227
228             // Remove all invalid bindings
229
if (invalidBindings.size() > 0)
230             {
231                 lock.writeLock().lock();
232                 
233                 try
234                 {
235                     for (B invalidBinding : invalidBindings)
236                     {
237                         cache.remove(invalidBinding);
238                         
239                         if (logger.isDebugEnabled())
240                             logger.debug("Cleared " + cacheDescription + " cache for " + invalidBinding + " and policy " + getPolicyClass());
241                     }
242                 }
243                 finally
244                 {
245                     lock.writeLock().unlock();
246                 }
247             }
248         }
249     }
250     
251 }
252
Popular Tags