1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.services.cms.lock.impl;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25
26 import javax.jcr.Node;
27 import javax.jcr.NodeIterator;
28 import javax.jcr.PathNotFoundException;
29 import javax.jcr.RepositoryException;
30 import javax.jcr.Session;
31 import javax.jcr.query.Query;
32 import javax.jcr.query.QueryResult;
33
34 import org.exoplatform.container.component.ComponentPlugin;
35 import org.exoplatform.container.xml.InitParams;
36 import org.exoplatform.services.cache.CacheService;
37 import org.exoplatform.services.cache.ExoCache;
38 import org.exoplatform.services.cms.lock.LockService;
39 import org.exoplatform.services.jcr.RepositoryService;
40 import org.exoplatform.services.jcr.core.ManageableRepository;
41 import org.exoplatform.services.jcr.ext.common.SessionProvider;
42 import org.exoplatform.services.log.ExoLogger;
43 import org.exoplatform.services.log.Log;
44 import org.exoplatform.services.security.ConversationState;
45 import org.exoplatform.services.security.Identity;
46 import org.exoplatform.services.security.IdentityConstants;
47 import org.exoplatform.services.security.MembershipEntry;
48 import org.exoplatform.services.wcm.core.NodetypeConstant;
49 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
50 import org.picocontainer.Startable;
51
52
53
54
55
56
57
58
59 public class LockServiceImpl implements LockService, Startable {
60
61 private final String SETTING_LOCK="SETTING_LOCK";
62 private final String PRE_SETTING_LOCK="PRE_SETTING_LOCK";
63 private final String CACHE_NAME = "ecms.LockService";
64
65 private ExoCache<String, List<String>> settingLockList;
66 private List<LockGroupsOrUsersPlugin> lockGroupsOrUsersPlugin_ = new ArrayList<LockGroupsOrUsersPlugin>();
67 private static final Log LOG = ExoLogger.getLogger(LockServiceImpl.class.getName());
68 private HashMap<String, Map<String, String>> lockHolding = new HashMap<String, Map<String, String>>();
69
70
71
72
73
74
75 public LockServiceImpl(InitParams params, CacheService cacheService) throws Exception {
76
77 settingLockList = cacheService.getCacheInstance(CACHE_NAME);
78 }
79
80
81
82
83
84 public void addLockGroupsOrUsersPlugin(ComponentPlugin plugin) {
85 if (plugin instanceof LockGroupsOrUsersPlugin)
86 lockGroupsOrUsersPlugin_.add((LockGroupsOrUsersPlugin)plugin);
87 }
88
89
90
91
92 @Override
93 public List<String> getPreSettingLockList(){
94 return settingLockList.get(PRE_SETTING_LOCK);
95 }
96
97
98
99
100 public List<String> getAllGroupsOrUsersForLock() throws Exception {
101 return settingLockList.get(SETTING_LOCK);
102 }
103
104
105
106
107 public void addGroupsOrUsersForLock(String groupsOrUsers) throws Exception {
108 List<String> _settingLockList = settingLockList.get(SETTING_LOCK);
109 if (_settingLockList!=null && !_settingLockList.contains(groupsOrUsers)) {
110 _settingLockList.add(groupsOrUsers);
111 settingLockList.put(SETTING_LOCK, _settingLockList);
112 }
113 }
114
115
116
117
118 public void removeGroupsOrUsersForLock(String groupsOrUsers) throws Exception {
119 List<String> _settingLockList = settingLockList.get(SETTING_LOCK);
120 if (_settingLockList!=null && _settingLockList.contains(groupsOrUsers)) {
121 _settingLockList.remove(groupsOrUsers);
122 settingLockList.put(SETTING_LOCK, _settingLockList);
123 }
124 }
125
126
127
128
129 public void start() {
130 lockHolding.clear();
131 settingLockList.clearCache();
132
133 removeLocks();
134 List<String> _settingLockList = new ArrayList<String>();
135 List<String> _preSettingLockList = new ArrayList<String>();
136 for(LockGroupsOrUsersPlugin plugin : lockGroupsOrUsersPlugin_) {
137 _settingLockList.addAll(plugin.initGroupsOrUsers());
138 _preSettingLockList.addAll(plugin.initGroupsOrUsers());
139 }
140 settingLockList.put(SETTING_LOCK, _settingLockList);
141 settingLockList.put(PRE_SETTING_LOCK, _preSettingLockList);
142 }
143
144
145
146
147 public void stop() {
148 lockHolding.clear();
149 settingLockList.clearCache();
150 }
151
152
153
154
155 @Override
156 public HashMap<String, Map<String, String>> getLockHolding() {
157 return lockHolding;
158 }
159
160
161
162
163 @Override
164 public void putToLockHoding(String userId, Map<String, String> lockedNodesInfo) {
165 lockHolding.put(userId, lockedNodesInfo);
166 }
167
168
169
170
171 @Override
172 public Map<String, String> getLockInformation(String userId) {
173 return lockHolding.get(userId);
174 }
175
176
177
178
179 @Override
180 public void removeLocksOfUser(String userId) {
181 SessionProvider sessionProvider = SessionProvider.createSystemProvider();
182 RepositoryService repositoryService = WCMCoreUtils.getService(RepositoryService.class);
183 if (LOG.isInfoEnabled()) {
184 LOG.info("Removing all locked nodes of user " + userId);
185 }
186 Map<String,String> lockedNodes = lockHolding.get(userId);
187 if(lockedNodes == null || lockedNodes.values().isEmpty()) return;
188 try {
189 for(Iterator<String> iter = lockedNodes.keySet().iterator(); iter.hasNext();) {
190 try {
191
192 String key = iter.next();
193 String[] temp = key.split(":/:");
194 String nodePath = temp[1];
195 String[] location = temp[0].split("/::/");
196 String workspaceName = location[1] ;
197 Session session = sessionProvider.getSession(workspaceName, repositoryService.getCurrentRepository());
198 String lockToken = lockedNodes.get(key);
199 session.addLockToken(lockToken);
200 Node node =null;
201 try {
202 node = (Node)session.getItem(nodePath);
203 }catch (PathNotFoundException e) {
204 if (LOG.isInfoEnabled()) {
205 LOG.info("Node " + nodePath + " has been already removed before");
206 }
207 continue;
208 }
209 if (!node.isCheckedOut() && node.isNodeType(NodetypeConstant.MIX_VERSIONABLE)) {
210 node.checkout();
211 }
212 if (node.isLocked()) {
213 node.unlock();
214 }
215 if (node.isNodeType("mix:lockable") && node.isCheckedOut()) {
216 node.removeMixin("mix:lockable");
217 }
218 node.save();
219 } catch (Exception e) {
220 if (LOG.isErrorEnabled()) {
221 LOG.error("Error while unlocking the locked nodes",e);
222 }
223 }
224 }
225 lockedNodes.clear();
226 } finally {
227 sessionProvider.close();
228 }
229 }
230
231
232
233
234 @Override
235 public void removeLocks() {
236 if (LOG.isInfoEnabled()) {
237 LOG.info("Clean all locked nodes in the system");
238 }
239 SessionProvider sessionProvider = SessionProvider.createSystemProvider();
240 RepositoryService repositoryService = WCMCoreUtils.getService(RepositoryService.class);
241 try {
242 String wsName = repositoryService.getCurrentRepository().getConfiguration().getDefaultWorkspaceName();
243 Session session = sessionProvider.getSession(wsName, repositoryService.getCurrentRepository());
244 String lockQueryStatement = "SELECT * from mix:lockable ORDER BY exo:dateCreated";
245 QueryResult queryResult = session.getWorkspace().getQueryManager().createQuery(lockQueryStatement, Query.SQL).execute();
246 NodeIterator nodeIter = queryResult.getNodes();
247 while(nodeIter.hasNext()) {
248 Node lockedNode = nodeIter.nextNode();
249
250 if (!lockedNode.isCheckedOut() && lockedNode.isNodeType(NodetypeConstant.MIX_VERSIONABLE)) {
251 lockedNode.checkout();
252 }
253 if(lockedNode.isLocked()) {
254 lockedNode.unlock();
255 }
256 if (lockedNode.isNodeType("mix:lockable") && lockedNode.isCheckedOut()) {
257 lockedNode.removeMixin("mix:lockable");
258 }
259 lockedNode.save();
260 }
261 } catch(RepositoryException re) {
262 if (LOG.isErrorEnabled()) {
263 LOG.error("Error while unlocking the locked nodes", re);
264 }
265 } finally {
266 sessionProvider.close();
267 }
268 }
269
270
271
272
273 @Override
274 public String getLockTokenOfUser(Node node) throws Exception {
275 String key = createLockKey(node);
276 String userId = ConversationState.getCurrent().getIdentity().getUserId();
277 if(userId == null) userId = IdentityConstants.ANONIM;
278 Map<String,String> lockedNodesInfo = getLockInformation(userId);
279 if ((lockedNodesInfo != null) && (lockedNodesInfo.get(key) != null)) {
280 return lockedNodesInfo.get(key);
281 }
282 return null;
283 }
284
285
286
287
288 @Override
289 public String createLockKey(Node node) throws Exception {
290 StringBuffer buffer = new StringBuffer();
291 Session session = node.getSession();
292 String repositoryName = ((ManageableRepository)session.getRepository()).getConfiguration().getName();
293 String userId = ConversationState.getCurrent().getIdentity().getUserId();
294 if(userId == null) userId = IdentityConstants.ANONIM;
295 buffer.append(repositoryName).append("/::/")
296 .append(session.getWorkspace().getName()).append("/::/")
297 .append(userId).append(":/:")
298 .append(node.getPath());
299 return buffer.toString();
300 }
301
302
303
304
305 @Override
306 public String createLockKey(Node node, String userId) throws Exception {
307 StringBuffer buffer = new StringBuffer();
308 Session session = node.getSession();
309 String repositoryName = ((ManageableRepository)session.getRepository()).getConfiguration().getName();
310 if(userId == null) userId = IdentityConstants.ANONIM;
311 buffer.append(repositoryName).append("/::/")
312 .append(session.getWorkspace().getName()).append("/::/")
313 .append(userId).append(":/:")
314 .append(node.getPath());
315 return buffer.toString();
316 }
317
318
319
320
321 @Override
322 public String getLockToken(Node node) throws Exception {
323 String key = createLockKey(node);
324 Identity currentIdentity = ConversationState.getCurrent().getIdentity();
325 String userId = currentIdentity.getUserId();
326 if(userId == null) userId = IdentityConstants.ANONIM;
327 Map<String,String> lockedNodesInfo = getLockInformation(userId);
328 if ((lockedNodesInfo != null) && (lockedNodesInfo.get(key) != null)) {
329 return lockedNodesInfo.get(key);
330 }
331
332 Collection<MembershipEntry> collection = currentIdentity.getMemberships();
333 String keyPermission;
334 for(MembershipEntry membership : collection) {
335 StringBuffer permissionBuffer = new StringBuffer();
336 permissionBuffer.append(membership.getMembershipType()).append(":").append(membership.getGroup());
337 if ((permissionBuffer != null) && (permissionBuffer.toString().length() > 0)) {
338 keyPermission = createLockKey(node, permissionBuffer.toString());
339 lockedNodesInfo = getLockInformation(permissionBuffer.toString());
340 if ((lockedNodesInfo != null) && (lockedNodesInfo.get(keyPermission) != null)) {
341 return lockedNodesInfo.get(keyPermission);
342 }
343 }
344 }
345 return null;
346 }
347
348
349
350
351 @Override
352 public void changeLockToken(String srcPath, Node newNode) throws Exception {
353 String newKey = createLockKey(newNode);
354 String oldKey = getOldLockKey(srcPath, newNode);
355 String userId = ConversationState.getCurrent().getIdentity().getUserId();
356 if(userId == null) userId = IdentityConstants.ANONIM;
357 Map<String,String> lockedNodesInfo = getLockInformation(userId);
358 if(lockedNodesInfo == null) {
359 lockedNodesInfo = new HashMap<String,String>();
360 }
361 if(lockedNodesInfo.containsKey(oldKey)) {
362 lockedNodesInfo.put(newKey, lockedNodesInfo.get(oldKey));
363 lockedNodesInfo.remove(oldKey);
364 }
365 putToLockHoding(userId, lockedNodesInfo);
366 }
367
368
369
370
371 @Override
372 public void changeLockToken(Node oldNode, Node newNode) throws Exception {
373 String newKey = createLockKey(newNode);
374 String oldKey = createLockKey(oldNode);
375 String userId = ConversationState.getCurrent().getIdentity().getUserId();
376 if(userId == null) userId = IdentityConstants.ANONIM;
377 Map<String,String> lockedNodesInfo = getLockInformation(userId);
378 if(lockedNodesInfo == null) {
379 lockedNodesInfo = new HashMap<String,String>();
380 }
381 lockedNodesInfo.remove(oldKey) ;
382 lockedNodesInfo.put(newKey,newNode.getLock().getLockToken());
383 putToLockHoding(userId,lockedNodesInfo);
384 }
385
386
387
388
389 @Override
390 public String getOldLockKey(String srcPath, Node node) throws Exception {
391 StringBuffer buffer = new StringBuffer();
392 Session session = node.getSession();
393 String repositoryName = ((ManageableRepository)session.getRepository()).getConfiguration().getName();
394 buffer.append(repositoryName).append("/::/")
395 .append(session.getWorkspace().getName()).append("/::/")
396 .append(session.getUserID()).append(":/:")
397 .append(srcPath);
398 return buffer.toString();
399 }
400 }