1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.settings;
20
21 import java.io.IOError;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.io.PrintStream;
26 import java.io.PrintWriter;
27 import java.io.Reader;
28 import java.io.Writer;
29 import java.util.AbstractSet;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.Enumeration;
33 import java.util.InvalidPropertiesFormatException;
34 import java.util.Iterator;
35 import java.util.Map;
36 import java.util.Properties;
37 import java.util.Set;
38 import java.util.function.BiConsumer;
39 import java.util.function.BiFunction;
40 import java.util.function.Consumer;
41 import java.util.function.Function;
42 import java.util.function.Supplier;
43
44 class WrapperProperties extends Properties {
45
46 final Supplier<Map<String, String>> getter;
47 final Consumer<Properties> setter;
48
49 WrapperProperties(Supplier<Map<String, String>> getter, Consumer<Properties> setter) {
50 this.getter = getter;
51 this.setter = setter;
52 }
53
54 @Override
55 public String getProperty(String key) {
56 return getter.get().get(key);
57 }
58
59 @Override
60 public String getProperty(String key, String defaultValue) {
61 return getter.get().getOrDefault(key, defaultValue);
62 }
63
64 @Override
65 public Enumeration<?> propertyNames() {
66 return Collections.enumeration(getter.get().keySet());
67 }
68
69 @Override
70 public Set<String> stringPropertyNames() {
71 return getter.get().keySet();
72 }
73
74 @Override
75 public void list(PrintStream out) {
76 throw new UnsupportedOperationException();
77 }
78
79 @Override
80 public void list(PrintWriter out) {
81 throw new UnsupportedOperationException();
82 }
83
84 @Override
85 public int size() {
86 return getter.get().size();
87 }
88
89 @Override
90 public boolean isEmpty() {
91 return getter.get().isEmpty();
92 }
93
94 @Override
95 public Enumeration<Object> keys() {
96 return Collections.enumeration((Set) getter.get().keySet());
97 }
98
99 @Override
100 public Enumeration<Object> elements() {
101 return Collections.enumeration((Collection) getter.get().values());
102 }
103
104 @Override
105 public boolean contains(Object value) {
106 return getter.get().containsKey(value != null ? value.toString() : null);
107 }
108
109 @Override
110 public boolean containsValue(Object value) {
111 return getter.get().containsValue(value);
112 }
113
114 @Override
115 public boolean containsKey(Object key) {
116 return getter.get().containsKey(key);
117 }
118
119 @Override
120 public Object get(Object key) {
121 return getter.get().get(key);
122 }
123
124 @Override
125 public synchronized String toString() {
126 return getter.get().toString();
127 }
128
129 @Override
130 public Set<Object> keySet() {
131 return (Set) getter.get().keySet();
132 }
133
134 @Override
135 public Collection<Object> values() {
136 return (Collection) getter.get().values();
137 }
138
139 @Override
140 public Set<Map.Entry<Object, Object>> entrySet() {
141 Set<Map.Entry<String, String>> set = getter.get().entrySet();
142 return new AbstractSet<Map.Entry<Object, Object>>() {
143 @Override
144 public Iterator<Map.Entry<Object, Object>> iterator() {
145 Iterator<Map.Entry<String, String>> it = set.iterator();
146 return new Iterator<Map.Entry<Object, Object>>() {
147 @Override
148 public boolean hasNext() {
149 return it.hasNext();
150 }
151
152 @Override
153 public Map.Entry<Object, Object> next() {
154 Map.Entry<String, String> entry = it.next();
155 return new Map.Entry<Object, Object>() {
156 @Override
157 public Object getKey() {
158 return entry.getKey();
159 }
160
161 @Override
162 public Object getValue() {
163 return entry.getValue();
164 }
165
166 @Override
167 public Object setValue(Object value) {
168 return writeOperation(p -> p.put(entry.getKey(), value));
169 }
170 };
171 }
172 };
173 }
174
175 @Override
176 public int size() {
177 return set.size();
178 }
179 };
180 }
181
182 @Override
183 public synchronized boolean equals(Object o) {
184 if (o instanceof WrapperProperties wrapperProperties) {
185 o = wrapperProperties.getter.get();
186 }
187 return getter.get().equals(o);
188 }
189
190 @Override
191 public synchronized int hashCode() {
192 return getter.get().hashCode();
193 }
194
195 @Override
196 public Object getOrDefault(Object key, Object defaultValue) {
197 return getter.get().getOrDefault(key, defaultValue != null ? defaultValue.toString() : null);
198 }
199
200 @Override
201 public synchronized void forEach(BiConsumer<? super Object, ? super Object> action) {
202 getter.get().forEach(action);
203 }
204
205 interface WriteOp<T> {
206 T perform(Properties props);
207 }
208
209 interface WriteOpVoid {
210 void perform(Properties props);
211 }
212
213 private <T> T writeOperation(WriteOp<T> runner) {
214 Properties props = new Properties();
215 props.putAll(getter.get());
216 T ret = runner.perform(props);
217 if (!props.equals(getter.get())) {
218 setter.accept(props);
219 }
220 return ret;
221 }
222
223 private void writeOperationVoid(WriteOpVoid runner) {
224 Properties props = new Properties();
225 props.putAll(getter.get());
226 runner.perform(props);
227 if (!props.equals(getter.get())) {
228 setter.accept(props);
229 }
230 }
231
232 @Override
233 public synchronized Object setProperty(String key, String value) {
234 return writeOperation(p -> p.setProperty(key, value));
235 }
236
237 @Override
238 public synchronized Object put(Object key, Object value) {
239 return writeOperation(p -> p.put(key, value));
240 }
241
242 @Override
243 public synchronized Object remove(Object key) {
244 return writeOperation(p -> p.remove(key));
245 }
246
247 @Override
248 public synchronized void putAll(Map<?, ?> t) {
249 writeOperationVoid(p -> p.putAll(t));
250 }
251
252 @Override
253 public synchronized void clear() {
254 writeOperationVoid(Properties::clear);
255 }
256
257 @Override
258 public synchronized void replaceAll(BiFunction<? super Object, ? super Object, ?> function) {
259 writeOperationVoid(p -> p.replaceAll(function));
260 }
261
262 @Override
263 public synchronized Object putIfAbsent(Object key, Object value) {
264 return writeOperation(p -> p.putIfAbsent(key, value));
265 }
266
267 @Override
268 public synchronized boolean remove(Object key, Object value) {
269 return writeOperation(p -> p.remove(key, value));
270 }
271
272 @Override
273 public synchronized boolean replace(Object key, Object oldValue, Object newValue) {
274 return writeOperation(p -> p.replace(key, oldValue, newValue));
275 }
276
277 @Override
278 public synchronized Object replace(Object key, Object value) {
279 return writeOperation(p -> p.replace(key, value));
280 }
281
282 @Override
283 public synchronized Object computeIfAbsent(Object key, Function<? super Object, ?> mappingFunction) {
284 return writeOperation(p -> p.computeIfAbsent(key, mappingFunction));
285 }
286
287 @Override
288 public synchronized Object computeIfPresent(
289 Object key, BiFunction<? super Object, ? super Object, ?> remappingFunction) {
290 return writeOperation(p -> p.computeIfPresent(key, remappingFunction));
291 }
292
293 @Override
294 public synchronized Object compute(Object key, BiFunction<? super Object, ? super Object, ?> remappingFunction) {
295 return writeOperation(p -> p.compute(key, remappingFunction));
296 }
297
298 @Override
299 public synchronized Object merge(
300 Object key, Object value, BiFunction<? super Object, ? super Object, ?> remappingFunction) {
301 return writeOperation(p -> p.merge(key, value, remappingFunction));
302 }
303
304 @Override
305 public synchronized void load(Reader reader) throws IOException {
306 try {
307 writeOperationVoid(p -> {
308 try {
309 p.load(reader);
310 } catch (IOException e) {
311 throw new IOError(e);
312 }
313 });
314 } catch (IOError e) {
315 throw (IOException) e.getCause();
316 }
317 }
318
319 @Override
320 public synchronized void load(InputStream inStream) throws IOException {
321 try {
322 writeOperationVoid(p -> {
323 try {
324 p.load(inStream);
325 } catch (IOException e) {
326 throw new IOError(e);
327 }
328 });
329 } catch (IOError e) {
330 throw (IOException) e.getCause();
331 }
332 }
333
334 @Override
335 public void save(OutputStream out, String comments) {
336 Properties props = new Properties();
337 props.putAll(getter.get());
338 props.save(out, comments);
339 }
340
341 @Override
342 public void store(Writer writer, String comments) throws IOException {
343 Properties props = new Properties();
344 props.putAll(getter.get());
345 props.store(writer, comments);
346 }
347
348 @Override
349 public void store(OutputStream out, String comments) throws IOException {
350 Properties props = new Properties();
351 props.putAll(getter.get());
352 props.store(out, comments);
353 }
354
355 @Override
356 public synchronized void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException {
357 throw new UnsupportedOperationException();
358 }
359
360 @Override
361 public void storeToXML(OutputStream os, String comment) throws IOException {
362 Properties props = new Properties();
363 props.putAll(getter.get());
364 props.storeToXML(os, comment);
365 }
366
367 @Override
368 public void storeToXML(OutputStream os, String comment, String encoding) throws IOException {
369 Properties props = new Properties();
370 props.putAll(getter.get());
371 props.storeToXML(os, comment, encoding);
372 }
373
374
375 private Object writeReplace() throws java.io.ObjectStreamException {
376 Properties props = new Properties();
377 props.putAll(getter.get());
378 return props;
379 }
380 }