Merge with 2ad3c504ee5d73982c0ef23336276dc1fc9e165f
[pithos] / src / gr / ebs / gss / server / webdav / milton / GssMemoryLockManager.java
1 /*
2  * Copyright 2011 Electronic Business Systems Ltd.
3  *
4  * This file is part of GSS.
5  *
6  * GSS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSS.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 package gr.ebs.gss.server.webdav.milton;
20
21 import java.util.Date;
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.UUID;
25
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import com.bradmcevoy.http.LockInfo;
30 import com.bradmcevoy.http.LockResult;
31 import com.bradmcevoy.http.LockTimeout;
32 import com.bradmcevoy.http.LockToken;
33 import com.bradmcevoy.http.LockableResource;
34 import com.bradmcevoy.http.exceptions.NotAuthorizedException;
35 import com.ettrema.http.fs.LockManager;
36
37
38 /**
39  * @author kman
40  *
41  */
42 public class GssMemoryLockManager implements LockManager {
43
44     private static final Logger log = LoggerFactory.getLogger( GssMemoryLockManager.class );
45     /**
46      * maps current locks by the file associated with the resource
47      */
48     Map<String, CurrentLock> locksByFile;
49     Map<String, CurrentLock> locksByToken;
50
51     public GssMemoryLockManager() {
52         locksByFile = new HashMap<String, CurrentLock>();
53         locksByToken = new HashMap<String, CurrentLock>();
54     }
55
56     public synchronized LockResult lock( LockTimeout timeout, LockInfo lockInfo, LockableResource r ) {
57         GssResource resource = (GssResource) r;
58         LockToken currentLock = currentLock( resource );
59         if( currentLock != null ) {
60             return LockResult.failed( LockResult.FailureReason.ALREADY_LOCKED );
61         }
62
63         LockToken newToken = new LockToken( UUID.randomUUID().toString(), lockInfo, timeout );
64         CurrentLock newLock = new CurrentLock( resource.getUniqueId(), newToken, lockInfo.lockedByUser );
65         locksByFile.put( resource.getUniqueId(), newLock );
66         locksByToken.put( newToken.tokenId, newLock );
67         return LockResult.success( newToken );
68     }
69
70     public synchronized LockResult refresh( String tokenId, LockableResource resource ) {
71         CurrentLock curLock = locksByToken.get( tokenId );
72         if( curLock == null ) {
73             log.debug( "can't refresh because no lock");
74             return LockResult.failed( LockResult.FailureReason.PRECONDITION_FAILED );
75         } else {
76             curLock.token.setFrom( new Date() );
77             return LockResult.success( curLock.token );
78         }
79     }
80
81     public synchronized void unlock( String tokenId, LockableResource r ) throws NotAuthorizedException {
82         GssResource resource = (GssResource) r;
83         LockToken lockToken = currentLock( resource );
84         if( lockToken == null ) {
85             log.debug( "not locked" );
86             return;
87         }
88         if( lockToken.tokenId.equals( tokenId ) ) {
89             removeLock( lockToken );
90         } else {
91             throw new NotAuthorizedException( resource );
92         }
93     }
94
95     private LockToken currentLock( GssResource resource ) {
96         CurrentLock curLock = locksByFile.get( resource.getUniqueId() );
97         if( curLock == null ) return null;
98         LockToken token = curLock.token;
99         if( token.isExpired() ) {
100             removeLock( token );
101             return null;
102         } else {
103             return token;
104         }
105     }
106
107     private void removeLock( LockToken token ) {
108         log.debug( "removeLock: " + token.tokenId );
109         CurrentLock currentLock = locksByToken.get( token.tokenId );
110         if( currentLock != null ) {
111             locksByFile.remove( currentLock.file );
112             locksByToken.remove( currentLock.token.tokenId );
113         } else {
114             log.warn( "couldnt find lock: " + token.tokenId );
115         }
116     }
117
118     public LockToken getCurrentToken( LockableResource r ) {
119         GssResource resource = (GssResource) r;
120         CurrentLock lock = locksByFile.get( resource.getUniqueId() );
121         if( lock == null ) return null;
122         LockToken token = new LockToken();
123         token.info = new LockInfo( LockInfo.LockScope.EXCLUSIVE, LockInfo.LockType.WRITE, lock.lockedByUser, LockInfo.LockDepth.ZERO );
124         token.info.lockedByUser = lock.lockedByUser;
125         token.timeout = lock.token.timeout;
126         token.tokenId = lock.token.tokenId;
127         return token;
128     }
129
130     class CurrentLock {
131
132         final String file;
133         final LockToken token;
134         final String lockedByUser;
135
136         public CurrentLock( String file, LockToken token, String lockedByUser ) {
137             this.file = file;
138             this.token = token;
139             this.lockedByUser = lockedByUser;
140         }
141     }
142
143 }