1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.transaction.locking;
18
19 import java.util.concurrent.TimeUnit;
20
21 /**
22 * Default implementation of the {@link HierarchicalLockManager}.
23 *
24 * <p>
25 * It splits the path into segments and non-exclusively locks each segment
26 * beginning from the root. The final segment - which is supposed to be the
27 * resource to be locked itself - can either be locked exclusively or
28 * non-exclusively. Too choose between the two, provide the flag in
29 * {@link #lockInHierarchy(Object, String, boolean)}.
30 *
31 * <p>
32 * This implementation needs an ordinary {@link LockManager lock manager} that
33 * it delegates all locking calls to.
34 *
35 * <p>
36 * This implementation is <em>thread-safe</em>.
37 */
38 public class DefaultHierarchicalLockManager<M> implements HierarchicalLockManager<Object, M> {
39
40 private final String rootPath;
41
42 private final LockManager<Object, M> lm;
43
44 public DefaultHierarchicalLockManager(String rootPath, LockManager<Object, M> lm) {
45 this.rootPath = rootPath;
46 this.lm = lm;
47 }
48
49 public void lockInHierarchy(M resourceManager, String path, boolean exclusive)
50 throws LockException {
51
52
53 if (!path.startsWith(rootPath)) {
54 throw new LockException("Could not lock a path (" + path
55 + ") that is not under the rootPath (" + rootPath + ")");
56 }
57 String relativePath = path.substring(rootPath.length());
58
59
60 if (relativePath.length() == 0) {
61 lock(resourceManager, "/", exclusive);
62 return;
63 }
64
65
66 lock(resourceManager, "/", false);
67
68 String[] segments = relativePath.split("\\\\");
69 StringBuffer currentPath = new StringBuffer(relativePath.length());
70
71 currentPath.append('/');
72
73
74 for (int i = 1; i < segments.length; i++) {
75 String segment = segments[i];
76
77 currentPath.append(segment).append('/');
78 String key = currentPath.toString();
79
80 if (i == segments.length - 1) {
81
82 lock(resourceManager, key, exclusive);
83 } else {
84
85 lock(resourceManager, key, false);
86 }
87 }
88 }
89
90 public void endWork() {
91 lm.endWork();
92 }
93
94 public void lock(M managedResource, Object key, boolean exclusive) throws LockException {
95 lm.lock(managedResource, key, exclusive);
96 }
97
98 public void startWork(long timeout, TimeUnit unit) {
99 lm.startWork(timeout, unit);
100
101 }
102
103 public boolean tryLock(M managedResource, Object key, boolean exclusive) {
104 return lm.tryLock(managedResource, key, exclusive);
105 }
106 }