1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3;
18
19 import java.util.IdentityHashMap;
20 import java.util.Iterator;
21 import java.util.Map;
22 import java.util.NoSuchElementException;
23 import java.util.concurrent.atomic.AtomicInteger;
24
25
26
27
28
29
30
31 public class SynchronizedArithmetic extends JexlArithmetic {
32
33
34
35 private final Monitor monitor;
36
37
38
39
40
41
42 protected SynchronizedArithmetic(final Monitor monitor, final boolean strict) {
43 super(strict);
44 this.monitor = monitor;
45 }
46
47
48
49
50
51
52
53 public static abstract class Monitor{
54
55 private final AtomicInteger enters = new AtomicInteger(0);
56
57 private final AtomicInteger exits = new AtomicInteger(0);
58
59
60
61
62
63 protected void monitorEnter(final Object o) {
64 enters.incrementAndGet();
65 }
66
67
68
69
70
71 protected void monitorExit(final Object o) {
72 exits.incrementAndGet();
73 }
74
75
76
77
78
79 public boolean isBalanced() {
80 return enters.get() == exits.get();
81 }
82
83
84
85
86
87 public int getCount() {
88 return enters.get();
89 }
90
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 static class SafeMonitor extends Monitor {
126 private final Map<Object, Object> monitored = new IdentityHashMap<>();
127
128 @Override
129 protected void monitorEnter(final Object o) {
130 Object guard;
131 try {
132 while (true) {
133 synchronized (monitored) {
134 guard = monitored.get(o);
135 if (guard == null) {
136 guard = new Object();
137 monitored.put(o, guard);
138 super.monitorEnter(o);
139 break;
140 }
141 }
142 synchronized (guard) {
143 guard.wait();
144 }
145 }
146 } catch (final InterruptedException xint) {
147
148 }
149 }
150
151 @Override protected void monitorExit(final Object o) {
152 final Object guard;
153 synchronized(monitored) {
154 guard = monitored.remove(o);
155 }
156 if (guard != null) {
157 synchronized(guard) {
158 guard.notifyAll();
159 }
160 super.monitorExit(o);
161 }
162 }
163 }
164
165
166
167
168
169 public class SynchronizedIterator implements Iterator<Object> {
170 private final Object monitored;
171 private Iterator<Object> iterator;
172
173 SynchronizedIterator(final Object locked, final Iterator<Object> ii) {
174 monitored = locked;
175 monitor.monitorEnter(monitored);
176 try {
177 iterator = ii;
178 } finally {
179 if (iterator == null) {
180 monitor.monitorExit(monitored);
181 }
182 }
183 }
184
185 @Override
186 protected void finalize() throws Throwable {
187 close();
188 super.finalize();
189 }
190
191
192 public void close() {
193 if (iterator != null) {
194 monitor.monitorExit(monitored);
195 iterator = null;
196 }
197 }
198
199 @Override
200 public boolean hasNext() {
201 if (iterator == null) {
202 return false;
203 }
204 final boolean n = iterator.hasNext();
205 if (!n) {
206 close();
207 }
208 return n;
209 }
210
211 @Override
212 public Object next() {
213 if (iterator == null) {
214 throw new NoSuchElementException();
215 }
216 return iterator.next();
217 }
218
219 @Override
220 public void remove() {
221 if (iterator != null) {
222 iterator.remove();
223 }
224 }
225 }
226
227
228
229
230
231
232
233
234 public Object arrayGet(final Map<?, ?> map, final Object key) {
235 monitor.monitorEnter(map);
236 try {
237 return map.get(key);
238 } finally {
239 monitor.monitorExit(map);
240 }
241 }
242
243
244
245
246
247
248
249 public void arraySet(final Map<Object, Object> map, final Object key, final Object value) {
250 monitor.monitorEnter(map);
251 try {
252 map.put(key, value);
253 } finally {
254 monitor.monitorExit(map);
255 }
256 }
257
258
259
260
261
262
263
264
265 public Object propertyGet(final Map<?, ?> map, final Object key) {
266 monitor.monitorEnter(map);
267 try {
268 return map.get(key);
269 } finally {
270 monitor.monitorExit(map);
271 }
272 }
273
274
275
276
277
278
279
280
281 public void propertySet(final Map<Object, Object> map, final Object key, final Object value) {
282 monitor.monitorEnter(map);
283 try {
284 map.put(key, value);
285 } finally {
286 monitor.monitorExit(map);
287 }
288 }
289
290
291
292
293
294
295 public Iterator<Object> forEach(final Map<Object, Object> map) {
296 return new SynchronizedIterator(map, map.values().iterator());
297 }
298 }