KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > services > lock > LockRegistry


1 //
2
// ____.
3
// __/\ ______| |__/\. _______
4
// __ .____| | \ | +----+ \
5
// _______| /--| | | - \ _ | : - \_________
6
// \\______: :---| : : | : | \________>
7
// |__\---\_____________:______: :____|____:_____\
8
// /_____|
9
//
10
// . . . i n j a h i a w e t r u s t . . .
11
//
12

13 package org.jahia.services.lock;
14
15 import java.util.HashMap JavaDoc;
16
17 import org.apache.log4j.Logger;
18 import org.jahia.content.ContentObject;
19 import org.jahia.content.JahiaObject;
20 import org.jahia.content.ObjectKey;
21 import org.jahia.exceptions.JahiaException;
22 import org.jahia.registries.ServicesRegistry;
23 import org.jahia.services.cache.Cache;
24 import org.jahia.services.cache.CacheEntry;
25 import org.jahia.services.usermanager.JahiaUser;
26
27 /**
28  *
29  * <p>Title: Jahia locking system implementation.</p>
30  * <p>Description:
31  * This registry store the Jahia lock defined in the engine or administration
32  * procedure.
33  *
34  * @todo Make this lock registry persistent for Jahia load balancing system.
35  *
36  * </p>
37  * <p>Copyright: MAP (Jahia Solutions S�rl 2003)</p>
38  * <p>Company: Jahia Solutions S�rl</p>
39  * @author MAP
40  * @version 1.0
41  */

42 public class LockRegistry extends LockService {
43
44     public final static String JavaDoc OWNER = "owner";
45     public final static String JavaDoc ID = "id";
46     public final static String JavaDoc STEALED = "stealed";
47     public final static String JavaDoc TIME_REMAINING = "timeRemaining";
48     public final static String JavaDoc TIMEOUT = "timeout";
49
50     /**
51      * Return the unique registry instance. If the instance does not exist,
52      * a new instance is created.
53      *
54      * @return The unique lock registry instance.
55      */

56     public synchronized static LockRegistry getInstance () {
57         if (lockRegistryInstance == null) {
58             lockRegistryInstance = new LockRegistry();
59         }
60         return lockRegistryInstance;
61     }
62
63     /**
64      * Acquire a lock if the appropriate prerequisites are complete.
65      *
66      * @param lockKey The lock key identifying the lock.
67      * @param owner The lock owner
68      * @param lockID The lock ID
69          * @param timeout The period in second during which the lock is valid. For a
70      * non expiration time lock use the constant NO_EXPIRATION_TIME.
71      * @return True if the lock was acquired, false otherwise.
72      */

73     public boolean acquire (LockKey lockKey, JahiaUser owner,
74                                          String JavaDoc lockID, int timeout) {
75         if (LockPrerequisites.getInstance().isLockAcquirable(lockKey, owner,
76             lockID, false)) {
77             Lock lock = getLock(lockKey);
78             if (lock == null) {
79                 lock = new Lock(owner, lockID, timeout);
80                 if (lockKey.getId() != 0) {
81                     putLock(lockKey, lock);
82                 }
83                 return true;
84             } else if (lock.hasExpired()) {
85                 lock.resetTimeout(timeout);
86                 lock.setOwner(owner);
87                 lock.setID(lockID);
88                 // Verify if lock was not already remove from the map. This case
89
// arrives when 'isAlreadyAcquired' method is called in the moment
90
// where the lock timeout has expired.
91
if (getLock(lockKey) == null) {
92                     if (lockKey.getId() != 0) {
93                         putLock(lockKey, lock);
94                     }
95                 }
96                 return true;
97             } else if (lock.getOwner().getUserKey().equals(owner.getUserKey())) {
98                 lock.resetTimeout(timeout);
99                 return true;
100             }
101         }
102         return false;
103     }
104
105     /**
106      * Test if a lock is acquireable if the appropriate prerequisites are
107      * complete.
108      *
109      * @param lockKey The lock key identifying the lock.
110      * @param owner The lock owner
111      * @param lockID The lock ID
112      * @return true if the lock is acquireable, false otherwise.
113      */

114     public boolean isAcquireable (LockKey lockKey, JahiaUser owner,
115                                                String JavaDoc lockID) {
116         if (LockPrerequisites.getInstance().isLockAcquirable(lockKey, owner,
117             lockID, true)) {
118             return true;
119         } else {
120             return false;
121         }
122     }
123
124     /**
125      * Reserve a lock with a defined expiration delay after which the lock is
126      * acquired to the user.
127      *
128      * @param lockKey The lock key identifying the lock.
129      * @param owner The lock owner
130      * @param lockID The lock identifier.
131      * @param timeout Lock time out.
132      * @param delay Lock delay...
133      * @return True if the lock can be reserved, false otherwise.
134      *
135      * @todo To implement
136      */

137     public boolean reserve (LockKey lockKey, JahiaUser owner,
138                                          String JavaDoc lockID, int timeout, int delay) {
139         return false;
140     }
141
142     /**
143      * Release the acquired lock. The lock should be in the correct context.
144      *
145      * @param lockKey The lock key identifying the lock.
146      * @param owner The lock owner
147      * @param lockID The lock identifier.
148      */

149     public void release (LockKey lockKey, JahiaUser owner,
150                                       String JavaDoc lockID) {
151         if (canRelease(lockKey, owner, lockID)) {
152             removeLock(lockKey);
153             LockPrerequisites.getInstance().resetPrerequisite(lockKey);
154         }
155     }
156
157     /**
158      * Return a lock information from a lock stored in the registry.
159      *
160      * @param lockKey The lock key identifying the lock.
161      * @return The lock attributes
162      */

163     public HashMap JavaDoc getInfo (LockKey lockKey) {
164         Lock lock = getLock(lockKey);
165         if (lock == null) {
166             return null;
167         }
168         HashMap JavaDoc lockInfo = new HashMap JavaDoc();
169         lockInfo.put(OWNER, lock.getOwner());
170         lockInfo.put(ID, lock.getID());
171         lockInfo.put(STEALED, new Boolean JavaDoc(lock.isStealed()));
172         lockInfo.put(TIME_REMAINING, getTimeRemaining(lockKey));
173         lockInfo.put(TIMEOUT, new Long JavaDoc(lock.getTimeout()));
174         return lockInfo;
175     }
176
177     /**
178      * Get the remaining time from a lock stored in the registry.
179      *
180      * @param lockKey The lock key identifying the lock.
181      * @return The lock tremaining time in second.
182      */

183     public Long JavaDoc getTimeRemaining (LockKey lockKey) {
184         Lock lock = getLock(lockKey);
185         if (lock == null) {
186             return null;
187         }
188         return new Long JavaDoc(lock.getTimeRemaining());
189     }
190
191     /**
192      * Change the lock context meaning that it can be stolen. Actually we admit
193      * that only user with administration priviliges has the right to perform
194      * this operation.
195      *
196      * @param lockKey The lock key identifying the lock.
197      * @param newOwner The new lock owner.
198      * @param lockID The new lock identifier.
199      */

200     public void steal(LockKey lockKey, JahiaUser newOwner, String JavaDoc lockID) {
201         if (hasAdminRights(lockKey, newOwner)) {
202             synchronized (this) {
203                 Lock lock = getLock(lockKey);
204                 lock.setOwner(newOwner);
205                 lock.setID(lockID);
206                 lock.setStealed(true);
207                 putLock(lockKey, lock);
208                 LockPrerequisites.getInstance().resetPrerequisite(lockKey);
209             }
210         }
211     }
212
213     /**
214      * Force to remove the lock from the registry meaning that it can be broken
215      * (nuked). Actually we admit that only user with administration priviliges
216      * has the right to perform this operation.
217      *
218      * @param lockKey The lock key identifying the lock.
219      * @param owner The lock owner.
220      * @param lockID The lock identifier.
221      *
222      * Sorry, should be called "break" but it is a reserved word ;)
223      */

224     public void nuke(LockKey lockKey, JahiaUser owner, String JavaDoc lockID) {
225         if (hasAdminRights(lockKey, owner)) {
226             synchronized (this) {
227                 removeLock(lockKey);
228                 LockPrerequisites.getInstance().resetPrerequisite(lockKey);
229             }
230         }
231     }
232
233     /**
234      * Return is the lock has been stolen or not.
235      *
236      * @param lockKey The lock key identifying the lock.
237      * @return True is the lock has benn stolen, false otherwise.
238      */

239     public boolean isStealed (LockKey lockKey) {
240         Lock lock = getLock(lockKey);
241         if (lock == null) {
242             return false;
243         }
244         return lock.isStealed();
245     }
246
247     /**
248      * Return if a lock has already been acquired.
249      *
250      * @param lockKey The lock key identifying the lock.
251      * @return True if the lock has already been acquired, false otherwise.
252      */

253     public boolean isAlreadyAcquired(LockKey lockKey) {
254         Lock lock = getLock(lockKey);
255         if (lock == null) {
256             return false; // By convention
257
}
258         if (lock.hasExpired()) {
259             synchronized (this) {
260                 removeLock(lockKey);
261                 LockPrerequisites.getInstance().resetPrerequisite(lockKey);
262             }
263             return false;
264         }
265         return true;
266     }
267
268     /**
269      * Define if a lock has been stolen in a specified context.
270      *
271      * @param lockKey The lock key identifying the lock.
272      * @param owner The lock owner.
273      * @param lockID The lock identifier.
274          * @return True if the lock has been stolen in the context, false otherwise.
275      */

276     public boolean isStealedInContext (LockKey lockKey,
277         JahiaUser owner, String JavaDoc lockID) {
278         if (isStealed(lockKey) &&
279             !isAlreadyAcquiredInContext(lockKey, owner, lockID)) {
280             return true;
281         }
282         return false;
283     }
284
285     /**
286      * Define if a lock has already been acquired in a specified context.
287      *
288      * @param lockKey The lock key identifying the lock.
289      * @param owner The lock owner.
290      * @param lockID The lock identifier.
291      * @return True if the lock has been already acquired in the context,
292      * false otherwise.
293      */

294     public boolean isAlreadyAcquiredInContext (LockKey lockKey,
295         JahiaUser owner, String JavaDoc lockID) {
296         Lock lock = getLock(lockKey);
297         if (lock == null) {
298             return false; // By convention
299
}
300         if (!isAlreadyAcquired(lockKey)) {
301             return false;
302         }
303         if (lock.getOwner().getUserKey().equals(owner.getUserKey())) {
304             return true;
305         }
306         return false;
307     }
308
309     /**
310      * Define if a lock can be released or not.
311      *
312      * @param lockKey The lock key identifying the lock.
313      * @param owner The lock owner.
314      * @param lockID The lock identifier.
315      * @return True if the lock can be released, false otherwise.
316      */

317     public boolean canRelease (LockKey lockKey, JahiaUser owner,
318                                             String JavaDoc lockID) {
319         Lock lock = getLock(lockKey);
320         if (lock == null) {
321             return true; // By convention
322
}
323         if (lock.hasExpired()) {
324             synchronized (this) {
325                 removeLock(lockKey);
326                 LockPrerequisites.getInstance().resetPrerequisite(lockKey);
327             }
328             return true;
329         }
330         if (lock.getOwner().getUserKey().equals(owner.getUserKey())) {
331             return true;
332         }
333         return false;
334     }
335
336     /**
337      * Define is the Jahia user has admin rights on a specified lock.
338      *
339      * @param lockKey The lock key identifying the lock.
340      * @param owner The lock owner.
341      * @return True if the user has admin rights, false otherwise.
342      */

343     public boolean hasAdminRights (LockKey lockKey,
344                                                 JahiaUser owner) {
345         ObjectKey objectKey = lockKey.getObjectKey();
346         // Try to get the content object from lock key if exists...
347
if (objectKey != null) {
348             try {
349                 ContentObject contentObject = (ContentObject) JahiaObject.
350                                               getInstance(objectKey);
351                 if (contentObject.checkAdminAccess(owner)) {
352                     return true;
353                 }
354             } catch (ClassNotFoundException JavaDoc cnfe) {
355                 logger.debug("Object '" + lockKey.getType() + "' not found !",
356                              cnfe);
357             }
358         }
359         // ... is the user root or site admin ?
360
else if (owner.isAdminMember(0) ||
361                  owner.isAdminMember(owner.getSiteID())) {
362             return true;
363         }
364         return false;
365     }
366
367     /**
368      * Purge all locks and lock prerequisites from memory and database,
369      * effectively freeing all the objects. This is a powerful operation and
370      * must be used with care as it might cause problems when people already
371      * have open popups.
372      */

373     public synchronized void purgeLocks() {
374         LockPrerequisites.getInstance().flush();
375         removeAllLocks();
376     }
377
378     /**
379      * Default constructor
380      */

381     private LockRegistry () {
382         try {
383             lockCache = ServicesRegistry.getInstance().getJahiaCacheServiceBis().
384                         createCache("LockCache");
385         } catch (JahiaException je) {
386             logger.error ("Error while creating lock cache", je);
387         }
388         logger.debug("Lock registry has been instanciated");
389     }
390
391     private void putLock (LockKey lockKey, Lock lock) {
392         if (lockCache.get(lockKey) != null) {
393             try {
394                 LockDB.getInstance().updateLock(lockKey, lock);
395             } catch (JahiaException je) {
396                 logger.error("Error while updating lock " + lockKey +
397                              "in database", je);
398             }
399         } else {
400             try {
401                 LockDB.getInstance().createLock(lockKey, lock);
402             } catch (JahiaException je) {
403                 logger.error("Error while creating the lock " + lockKey +
404                              "in the database", je);
405             }
406         }
407         lockCache.put(lockKey, lock);
408     }
409
410     private Lock getLock (LockKey lockKey) {
411         CacheEntry cacheEntry = lockCache.getCacheEntry(lockKey);
412         if (cacheEntry != null) {
413             /*
414             if (cacheEntry.getObject() == null) {
415                 logger.debug("Returning null object that was stored in the cache for to indicate inexistence LockKey"+lockKey + " in the database");
416             }
417             */

418             return (Lock) cacheEntry.getObject();
419         } else {
420             try {
421                 Lock lock = LockDB.getInstance().getLock(lockKey);
422                 // this will work even if the lock is null as we check for
423
// this in our getter method.
424
lockCache.put(lockKey, lock);
425                 return lock;
426             } catch (JahiaException je) {
427                 logger.error("Error while retrieving lock " + lockKey +
428                              " from database", je);
429                 return null;
430             }
431         }
432     }
433
434     private void removeLock (LockKey lockKey) {
435         lockCache.remove(lockKey);
436         try {
437             LockDB.getInstance().removeLock(lockKey);
438         } catch (JahiaException je) {
439             logger.error("Error while removing lock " + lockKey +
440                          " from the database ", je);
441         }
442     }
443
444     private void removeAllLocks() {
445         try {
446             LockDB.getInstance().removeAllLocks();
447         } catch (JahiaException je) {
448             logger.error("Error while removing all locks from the database ", je);
449         }
450         lockCache.flush();
451     }
452
453     private static LockRegistry lockRegistryInstance;
454
455     private Cache lockCache;
456
457     private static Logger logger = Logger.getLogger(LockRegistry.class);
458
459 }
460
Popular Tags