KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > lock > LockServiceImpl


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.lock;
18
19 import java.io.Serializable JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Calendar JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.Date JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.Set JavaDoc;
28
29 import org.alfresco.model.ContentModel;
30 import org.alfresco.repo.policy.JavaBehaviour;
31 import org.alfresco.repo.policy.PolicyComponent;
32 import org.alfresco.repo.policy.PolicyScope;
33 import org.alfresco.service.cmr.lock.LockService;
34 import org.alfresco.service.cmr.lock.LockStatus;
35 import org.alfresco.service.cmr.lock.LockType;
36 import org.alfresco.service.cmr.lock.NodeLockedException;
37 import org.alfresco.service.cmr.lock.UnableToAquireLockException;
38 import org.alfresco.service.cmr.lock.UnableToReleaseLockException;
39 import org.alfresco.service.cmr.repository.AspectMissingException;
40 import org.alfresco.service.cmr.repository.ChildAssociationRef;
41 import org.alfresco.service.cmr.repository.NodeRef;
42 import org.alfresco.service.cmr.repository.NodeService;
43 import org.alfresco.service.cmr.repository.StoreRef;
44 import org.alfresco.service.cmr.search.ResultSet;
45 import org.alfresco.service.cmr.search.SearchService;
46 import org.alfresco.service.cmr.security.AuthenticationService;
47 import org.alfresco.service.cmr.security.OwnableService;
48 import org.alfresco.service.namespace.NamespaceService;
49 import org.alfresco.service.namespace.QName;
50
51 /**
52  * Simple Lock service implementation
53  *
54  * @author Roy Wetherall
55  */

56 public class LockServiceImpl implements LockService
57 {
58     /**
59      * The node service
60      */

61     private NodeService nodeService;
62
63     /**
64      * The policy component
65      */

66     private PolicyComponent policyComponent;
67
68     /**
69      * List of node ref's to ignore when checking for locks
70      */

71     private Set JavaDoc<NodeRef> ignoreNodeRefs = new HashSet JavaDoc<NodeRef>();
72
73     /**
74      * The authentication service
75      */

76     private AuthenticationService authenticationService;
77
78     /**
79      * The ownable service
80      *
81      */

82     private OwnableService ownableService;
83     
84     /**
85      * The search service
86      */

87     private SearchService searchService;
88
89     /**
90      * Set the node service
91      *
92      * @param nodeService
93      * the node service
94      */

95     public void setNodeService(NodeService nodeService)
96     {
97         this.nodeService = nodeService;
98     }
99
100     /**
101      * Sets the policy component
102      *
103      * @param policyComponent
104      * the policy componentO
105      */

106     public void setPolicyComponent(PolicyComponent policyComponent)
107     {
108         this.policyComponent = policyComponent;
109     }
110
111     /**
112      * Sets the authentication service
113      *
114      * @param authenticationService
115      * the authentication service
116      */

117     public void setAuthenticationService(AuthenticationService authenticationService)
118     {
119         this.authenticationService = authenticationService;
120     }
121
122     /**
123      * Sets the ownable service
124      *
125      * @param ownableService
126      * the ownable service
127      */

128     public void setOwnableService(OwnableService ownableService)
129     {
130         this.ownableService = ownableService;
131     }
132     
133     /**
134      * Set the search service
135      *
136      * @param searchService the search service
137      */

138     public void setSearchService(SearchService searchService)
139     {
140         this.searchService = searchService;
141     }
142
143     /**
144      * Initialise methods called by Spring framework
145      */

146     public void initialise()
147     {
148         // Register the various class behaviours to enable lock checking
149
this.policyComponent.bindClassBehaviour(
150                 QName.createQName(NamespaceService.ALFRESCO_URI, "beforeCreateVersion"), ContentModel.ASPECT_LOCKABLE,
151                 new JavaBehaviour(this, "checkForLock"));
152         this.policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "beforeUpdateNode"),
153                 ContentModel.ASPECT_LOCKABLE, new JavaBehaviour(this, "checkForLock"));
154         this.policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
155                 ContentModel.ASPECT_LOCKABLE, new JavaBehaviour(this, "checkForLock"));
156
157         // Register onCopy class behaviour
158
this.policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyNode"),
159                 ContentModel.ASPECT_LOCKABLE, new JavaBehaviour(this, "onCopy"));
160
161         // Register the onCreateVersion behavior for the version aspect
162
this.policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateVersion"),
163                 ContentModel.ASPECT_LOCKABLE, new JavaBehaviour(this, "onCreateVersion"));
164     }
165     
166     /**
167      * @see org.alfresco.service.cmr.lock.LockService#lock(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, org.alfresco.service.cmr.lock.LockType)
168      */

169     public synchronized void lock(NodeRef nodeRef, LockType lockType)
170     {
171         // Lock with no expiration
172
lock(nodeRef, lockType, 0);
173     }
174
175     /**
176      * @see org.alfresco.service.cmr.lock.LockService#lock(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, org.alfresco.service.cmr.lock.LockType, int)
177      */

178     public synchronized void lock(NodeRef nodeRef, LockType lockType, int timeToExpire)
179     {
180         // Check for lock aspect
181
checkForLockApsect(nodeRef);
182         
183         // Get the current user name
184
String JavaDoc userName = getUserName();
185
186         // Set a default value
187
if (lockType == null)
188         {
189             lockType = LockType.WRITE_LOCK;
190         }
191
192         LockStatus currentLockStatus = getLockStatus(nodeRef, userName);
193         if (LockStatus.LOCKED.equals(currentLockStatus) == true)
194         {
195             // Error since we are trying to lock a locked node
196
throw new UnableToAquireLockException(nodeRef);
197         }
198         else if (LockStatus.NO_LOCK.equals(currentLockStatus) == true ||
199                  LockStatus.LOCK_EXPIRED.equals(currentLockStatus) == true ||
200                  LockStatus.LOCK_OWNER.equals(currentLockStatus) == true)
201         {
202             this.ignoreNodeRefs.add(nodeRef);
203             try
204             {
205                 // Set the current user as the lock owner
206
this.nodeService.setProperty(nodeRef, ContentModel.PROP_LOCK_OWNER, userName);
207                 this.nodeService.setProperty(nodeRef, ContentModel.PROP_LOCK_TYPE, lockType.toString());
208                 setExpiryDate(nodeRef, timeToExpire);
209             }
210             finally
211             {
212                 this.ignoreNodeRefs.remove(nodeRef);
213             }
214         }
215     }
216
217     /**
218      * Helper method to set the expiry date based on the time to expire provided
219      *
220      * @param nodeRef the node reference
221      * @param timeToExpire the time to expire (in seconds)
222      */

223     private void setExpiryDate(NodeRef nodeRef, int timeToExpire)
224     {
225         // Set the expiry date
226
Date JavaDoc expiryDate = null;
227         if (timeToExpire > 0)
228         {
229             expiryDate = new Date JavaDoc();
230             Calendar JavaDoc calendar = Calendar.getInstance();
231             calendar.setTime(expiryDate);
232             calendar.add(Calendar.SECOND, timeToExpire);
233             expiryDate = calendar.getTime();
234         }
235         
236         this.nodeService.setProperty(nodeRef, ContentModel.PROP_EXPIRY_DATE, expiryDate);
237     }
238
239     /**
240      * @see org.alfresco.service.cmr.lock.LockService#lock(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, org.alfresco.service.cmr.lock.LockType, int, boolean)
241      */

242     public synchronized void lock(NodeRef nodeRef, LockType lockType, int timeToExpire, boolean lockChildren)
243             throws UnableToAquireLockException
244     {
245         lock(nodeRef, lockType, timeToExpire);
246
247         if (lockChildren == true)
248         {
249             Collection JavaDoc<ChildAssociationRef> childAssocRefs = this.nodeService.getChildAssocs(nodeRef);
250             for (ChildAssociationRef childAssocRef : childAssocRefs)
251             {
252                 lock(childAssocRef.getChildRef(), lockType, timeToExpire, lockChildren);
253             }
254         }
255     }
256
257     /**
258      * @see org.alfresco.service.cmr.lock.LockService#lock(java.util.Collection, java.lang.String, org.alfresco.service.cmr.lock.LockType, int)
259      */

260     public synchronized void lock(Collection JavaDoc<NodeRef> nodeRefs, LockType lockType, int timeToExpire)
261             throws UnableToAquireLockException
262     {
263         // Lock each of the specifed nodes
264
for (NodeRef nodeRef : nodeRefs)
265         {
266             lock(nodeRef, lockType, timeToExpire);
267         }
268     }
269
270     /**
271      * @see org.alfresco.service.cmr.lock.LockService#unlock(NodeRef, String)
272      */

273     public synchronized void unlock(NodeRef nodeRef) throws UnableToReleaseLockException
274     {
275         // Check for lock aspect
276
checkForLockApsect(nodeRef);
277         
278         // Get the current user name
279
//String userName = getUserName();
280

281         //LockStatus lockStatus = getLockStatus(nodeRef, userName);
282
//if (LockStatus.LOCKED.equals(lockStatus) == true)
283
// {
284
// // Error since the lock can only be released by the lock owner
285
// throw new UnableToReleaseLockException(nodeRef);
286
// }
287
// else if (LockStatus.LOCK_OWNER.equals(lockStatus) == true)
288
// {
289
this.ignoreNodeRefs.add(nodeRef);
290             try
291             {
292                 // Clear the lock owner
293
this.nodeService.setProperty(nodeRef, ContentModel.PROP_LOCK_OWNER, null);
294                 this.nodeService.setProperty(nodeRef, ContentModel.PROP_LOCK_TYPE, null);
295             } finally
296             {
297                 this.ignoreNodeRefs.remove(nodeRef);
298             }
299         //}
300
}
301
302     /**
303      * @see org.alfresco.service.cmr.lock.LockService#unlock(NodeRef, String,
304      * boolean)
305      */

306     public synchronized void unlock(NodeRef nodeRef, boolean unlockChildren)
307             throws UnableToReleaseLockException
308     {
309         // Unlock the parent
310
unlock(nodeRef);
311
312         if (unlockChildren == true)
313         {
314             // Get the children and unlock them
315
Collection JavaDoc<ChildAssociationRef> childAssocRefs = this.nodeService.getChildAssocs(nodeRef);
316             for (ChildAssociationRef childAssocRef : childAssocRefs)
317             {
318                 unlock(childAssocRef.getChildRef(), unlockChildren);
319             }
320         }
321     }
322
323     /**
324      * @see org.alfresco.repo.lock.LockService#unlock(Collection<NodeRef>,
325      * String)
326      */

327     public synchronized void unlock(Collection JavaDoc<NodeRef> nodeRefs) throws UnableToReleaseLockException
328     {
329         for (NodeRef nodeRef : nodeRefs)
330         {
331             unlock(nodeRef);
332         }
333     }
334
335     /**
336      * @see org.alfresco.service.cmr.lock.LockService#getLockStatus(NodeRef)
337      */

338     public LockStatus getLockStatus(NodeRef nodeRef)
339     {
340         return getLockStatus(nodeRef, getUserName());
341     }
342
343     /**
344      * Gets the lock statuc for a node and a user name
345      *
346      * @param nodeRef the node reference
347      * @param userName the user name
348      * @return the lock status
349      */

350     private LockStatus getLockStatus(NodeRef nodeRef, String JavaDoc userName)
351     {
352         LockStatus result = LockStatus.NO_LOCK;
353
354         if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE) == true)
355
356         {
357             // Get the current lock owner
358
String JavaDoc currentUserRef = (String JavaDoc) this.nodeService.getProperty(nodeRef, ContentModel.PROP_LOCK_OWNER);
359             String JavaDoc owner = ownableService.getOwner(nodeRef);
360             if (currentUserRef != null)
361             {
362                 Date JavaDoc expiryDate = (Date JavaDoc)this.nodeService.getProperty(nodeRef, ContentModel.PROP_EXPIRY_DATE);
363                 if (expiryDate != null && expiryDate.before(new Date JavaDoc()) == true)
364                 {
365                     // Indicate that the lock has expired
366
result = LockStatus.LOCK_EXPIRED;
367                 }
368                 else
369                 {
370                     if (currentUserRef.equals(userName) == true)
371                     {
372                         result = LockStatus.LOCK_OWNER;
373                     }
374                     else if ((owner != null) && owner.equals(userName))
375                     {
376                         result = LockStatus.LOCK_OWNER;
377                     }
378                     else
379                     {
380                         result = LockStatus.LOCKED;
381                     }
382                 }
383             }
384
385         }
386         return result;
387
388     }
389
390     /**
391      * @see LockService#getLockType(NodeRef)
392      */

393     public LockType getLockType(NodeRef nodeRef)
394     {
395         LockType result = null;
396
397         if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE) == true)
398         {
399             String JavaDoc lockTypeString = (String JavaDoc) this.nodeService.getProperty(nodeRef, ContentModel.PROP_LOCK_TYPE);
400             if (lockTypeString != null)
401             {
402                 result = LockType.valueOf(lockTypeString);
403             }
404         }
405
406         return result;
407     }
408
409     /**
410      * Checks for the lock aspect. Adds if missing.
411      *
412      * @param nodeRef
413      * the node reference
414      */

415     private void checkForLockApsect(NodeRef nodeRef)
416     {
417         if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE) == false)
418         {
419             this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_LOCKABLE, null);
420         }
421     }
422
423     /**
424      * @see LockService#checkForLock(NodeRef)
425      */

426     public void checkForLock(NodeRef nodeRef) throws NodeLockedException
427     {
428         String JavaDoc userName = getUserName();
429  
430         // Ensure we have found a node reference
431
if (nodeRef != null && userName != null)
432         {
433             // Check to see if should just ignore this node
434
if (this.ignoreNodeRefs.contains(nodeRef) == false)
435             {
436                 try
437                 {
438                     // Get the current lock status on the node ref
439
LockStatus currentLockStatus = getLockStatus(nodeRef, userName);
440
441                     LockType lockType = getLockType(nodeRef);
442                     if (LockType.WRITE_LOCK.equals(lockType) == true &&
443                         LockStatus.LOCKED.equals(currentLockStatus) == true)
444                     {
445                         // Error since we are trying to preform an operation
446
// on a locked node
447
throw new NodeLockedException(nodeRef);
448                     }
449                     else if (LockType.READ_ONLY_LOCK.equals(lockType) == true &&
450                              (LockStatus.LOCKED.equals(currentLockStatus) == true || LockStatus.LOCK_OWNER.equals(currentLockStatus) == true))
451                     {
452                         // Error since there is a read only lock on this object
453
// and all
454
// modifications are prevented
455
throw new NodeLockedException(nodeRef);
456                     }
457                 }
458                 catch (AspectMissingException exception)
459                 {
460                     // Ignore since this indicates that the node does not have
461
// the lock
462
// aspect applied
463
}
464             }
465         }
466     }
467
468     /**
469      * OnCopy behaviour implementation for the lock aspect.
470      * <p>
471      * Ensures that the propety values of the lock aspect are not copied onto
472      * the destination node.
473      *
474      * @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyNodePolicy#onCopyNode(QName,
475      * NodeRef, StoreRef, boolean, PolicyScope)
476      */

477     public void onCopy(QName sourceClassRef, NodeRef sourceNodeRef, StoreRef destinationStoreRef,
478             boolean copyToNewNode, PolicyScope copyDetails)
479     {
480         // Add the lock aspect, but do not copy any of the properties
481
copyDetails.addAspect(ContentModel.ASPECT_LOCKABLE);
482     }
483
484     /**
485      * OnCreateVersion behaviour for the lock aspect
486      * <p>
487      * Ensures that the property valies of the lock aspect are not 'frozen' in
488      * the version store.
489      *
490      * @param classRef
491      * the class reference
492      * @param versionableNode
493      * the versionable node reference
494      * @param versionProperties
495      * the version properties
496      * @param nodeDetails
497      * the details of the node to be versioned
498      */

499     public void onCreateVersion(QName classRef, NodeRef versionableNode, Map JavaDoc<String JavaDoc, Serializable JavaDoc> versionProperties,
500             PolicyScope nodeDetails)
501     {
502         // Add the lock aspect, but do not version the property values
503
nodeDetails.addAspect(ContentModel.ASPECT_LOCKABLE);
504     }
505
506     /**
507      * Get the current user reference
508      *
509      * @return the current user reference
510      */

511     private String JavaDoc getUserName()
512     {
513         return this.authenticationService.getCurrentUserName();
514     }
515
516     /**
517      * @see org.alfresco.service.cmr.lock.LockService#getLocks()
518      */

519     public List JavaDoc<NodeRef> getLocks(StoreRef storeRef)
520     {
521         return getLocks(
522                 storeRef,
523                 "ASPECT:\"" + ContentModel.ASPECT_LOCKABLE.toString() +
524                 "\" +@\\{http\\://www.alfresco.org/model/content/1.0\\}" + ContentModel.PROP_LOCK_OWNER.getLocalName() + ":\"" + getUserName() + "\"");
525     }
526     
527     /**
528      * Get the locks given a store and query string.
529      *
530      * @param storeRef the store reference
531      * @param query the query string
532      * @return the locked nodes
533      */

534     private List JavaDoc<NodeRef> getLocks(StoreRef storeRef, String JavaDoc query)
535     {
536         List JavaDoc<NodeRef> result = new ArrayList JavaDoc<NodeRef>();
537         ResultSet resultSet = null;
538         try
539         {
540             resultSet = this.searchService.query(
541                     storeRef,
542                     SearchService.LANGUAGE_LUCENE,
543                     query);
544             result = resultSet.getNodeRefs();
545         }
546         finally
547         {
548             if (resultSet != null)
549             {
550                 resultSet.close();
551             }
552         }
553         return result;
554     }
555
556     /**
557      * @see org.alfresco.service.cmr.lock.LockService#getLocks(org.alfresco.service.cmr.lock.LockType)
558      */

559     public List JavaDoc<NodeRef> getLocks(StoreRef storeRef, LockType lockType)
560     {
561         return getLocks(
562                 storeRef,
563                 "ASPECT:\"" + ContentModel.ASPECT_LOCKABLE.toString() +
564                 "\" +@\\{http\\://www.alfresco.org/model/content/1.0\\}" + ContentModel.PROP_LOCK_OWNER.getLocalName() + ":\"" + getUserName() + "\"" +
565                 " +@\\{http\\://www.alfresco.org/model/content/1.0\\}" + ContentModel.PROP_LOCK_TYPE.getLocalName() + ":\"" + lockType.toString() + "\"");
566     }
567 }
568
Popular Tags