1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package net.sf.prefixedproperties;
27
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.ObjectInputStream;
31 import java.io.ObjectOutputStream;
32 import java.io.OutputStream;
33 import java.io.OutputStreamWriter;
34 import java.io.PrintStream;
35 import java.io.PrintWriter;
36 import java.io.Reader;
37 import java.io.Serializable;
38 import java.io.Writer;
39 import java.nio.charset.Charset;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.Collection;
43 import java.util.Collections;
44 import java.util.Enumeration;
45 import java.util.HashMap;
46 import java.util.HashSet;
47 import java.util.Iterator;
48 import java.util.LinkedList;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.Map.Entry;
52 import java.util.Properties;
53 import java.util.Set;
54 import java.util.TreeMap;
55 import java.util.concurrent.locks.ReentrantReadWriteLock;
56
57 import org.apache.commons.lang.StringUtils;
58
59 import com.fasterxml.jackson.core.JsonEncoding;
60 import com.fasterxml.jackson.core.JsonFactory;
61 import com.fasterxml.jackson.core.JsonGenerator;
62 import com.fasterxml.jackson.core.JsonParser;
63 import com.fasterxml.jackson.core.JsonToken;
64 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
65 import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
66 import com.fasterxml.jackson.dataformat.yaml.YAMLParser;
67
68 import net.sf.prefixedproperties.config.DefaultPrefixConfig;
69 import net.sf.prefixedproperties.config.DynamicPrefixConfig;
70 import net.sf.prefixedproperties.config.PrefixConfig;
71 import net.sf.triemap.TrieMap;
72 import net.sf.triemap.TrieMap.TrieMapBackedProperties;
73
74
75
76
77
78
79
80
81
82
83
84 public class PrefixedProperties extends Properties implements Serializable {
85
86 private class DoubleEntry<T, P> {
87 private final T one;
88 private final P two;
89
90 private DoubleEntry(final T one, final P two) {
91 this.one = one;
92 this.two = two;
93 }
94
95 public T getOne() {
96 return one;
97 }
98
99 public P getTwo() {
100 return two;
101 }
102
103 @Override
104 public String toString() {
105 final StringBuilder sb = new StringBuilder("One:").append(one).append(" Two: ").append(two);
106 return sb.toString();
107 }
108
109 }
110
111
112
113
114 private static class EmptyPrefix extends DefaultPrefixConfig {
115
116
117 private final static long serialVersionUID = 1L;
118
119
120 private final static EmptyPrefix INSTANCE = new EmptyPrefix();
121
122
123
124
125
126
127 @Override
128 public final PrefixConfig clone() {
129 return EmptyPrefix.INSTANCE;
130 }
131 }
132
133
134
135
136 private final class PPEntry implements Map.Entry<Object, Object> {
137
138
139 private final Object key;
140
141
142 private final Object value;
143
144
145
146
147
148
149
150
151 private PPEntry(final Object aKey, final Object aValue) {
152 key = aKey;
153 value = aValue;
154 }
155
156
157
158
159
160
161 @Override
162 public Object getKey() {
163 try {
164 lock.readLock().lock();
165 return getUnprefixedKey(key);
166 } finally {
167 lock.readLock().unlock();
168 }
169 }
170
171
172
173
174
175
176 @Override
177 public Object getValue() {
178 return value;
179 }
180
181
182
183
184
185
186 @Override
187 public Object setValue(final Object aValue) {
188 return put(key, aValue);
189 }
190
191 @Override
192 public String toString() {
193 final StringBuilder builder = new StringBuilder();
194 builder.append("[key=").append(key).append(", value=").append(value).append("]");
195 return builder.toString();
196 }
197
198 }
199
200
201
202
203
204
205 private final class PrefixedPropertiesEnumerationImpl<E> implements PrefixedPropertiesEnumeration<E> {
206
207
208 private Iterator<E> it;
209
210
211 private E last;
212
213
214 private boolean isKey;
215
216
217
218
219
220
221 private PrefixedPropertiesEnumerationImpl(final Iterator<E> iterator) {
222 this(iterator, false);
223 }
224
225
226
227
228
229
230
231
232 private PrefixedPropertiesEnumerationImpl(final Iterator<E> iterator, final boolean isKeyParam) {
233 it = iterator;
234 isKey = isKeyParam;
235 }
236
237
238
239
240
241
242 @Override
243 public boolean hasMoreElements() {
244 return hasNext();
245 }
246
247
248
249
250
251
252 @Override
253 public boolean hasNext() {
254 return it.hasNext();
255 }
256
257
258
259
260
261
262 @Override
263 public Iterator<E> iterator() {
264 return this;
265 }
266
267
268
269
270
271
272 @Override
273 public E next() {
274 last = it.next();
275 return last;
276 }
277
278
279
280
281
282
283 @Override
284 public E nextElement() {
285 return next();
286 }
287
288
289
290
291
292
293 @Override
294 public void remove() {
295 if (isKey) {
296 PrefixedProperties.this.remove(last);
297 }
298 }
299
300 }
301
302
303
304
305
306
307
308
309 public static PrefixedProperties createCascadingPrefixProperties(final List<PrefixConfig> configs) {
310 PrefixedProperties properties = null;
311 for (final PrefixConfig config : configs) {
312 if (properties == null) {
313 properties = new PrefixedProperties((config == null) ? new DynamicPrefixConfig() : config);
314 } else {
315 properties = new PrefixedProperties(properties, (config == null) ? new DynamicPrefixConfig() : config);
316 }
317 }
318 return properties;
319 }
320
321
322
323
324
325
326
327
328 public static PrefixedProperties createCascadingPrefixProperties(final PrefixConfig... configs) {
329 PrefixedProperties properties = null;
330 for (final PrefixConfig config : configs) {
331 if (properties == null) {
332 properties = new PrefixedProperties((config == null) ? new DynamicPrefixConfig() : config);
333 } else {
334 properties = new PrefixedProperties(properties, (config == null) ? new DynamicPrefixConfig() : config);
335 }
336 }
337 return properties;
338 }
339
340
341
342
343
344
345
346
347
348 public static PrefixedProperties createCascadingPrefixProperties(final String prefixString) {
349 return prefixString.indexOf(PrefixConfig.PREFIXDELIMITER) != -1
350 ? createCascadingPrefixProperties(prefixString.split("\\" + PrefixConfig.PREFIXDELIMITER))
351 : createCascadingPrefixProperties(new String[] { prefixString });
352
353 }
354
355
356
357
358
359
360
361
362 public static PrefixedProperties createCascadingPrefixProperties(final String[] prefixes) {
363 PrefixedProperties properties = null;
364 for (final String aPrefix : prefixes) {
365 if (properties == null) {
366 properties = new PrefixedProperties(aPrefix);
367 } else {
368 properties = new PrefixedProperties(properties, aPrefix);
369 }
370 }
371 return properties;
372 }
373
374 private static final long serialVersionUID = 1L;
375
376 private transient ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
377
378 private PrefixConfig prefixes = new DynamicPrefixConfig();
379
380 private Properties properties = new TrieMap<Object>().asProperties();
381
382 private boolean mixDefaultAndLocalPrefixes = true;
383
384
385
386
387 public PrefixedProperties() {
388 }
389
390
391
392
393
394
395
396 public PrefixedProperties(final PrefixConfig config) {
397 setPrefixConfig(config);
398 }
399
400
401
402
403
404
405
406
407
408 public PrefixedProperties(final PrefixConfig config, final Properties defaults) {
409 this(defaults);
410 setPrefixConfig(config);
411 }
412
413
414
415
416
417
418
419
420
421 public PrefixedProperties(final PrefixedProperties props, final PrefixConfig config) {
422 properties = props;
423 setPrefixConfig(config);
424 }
425
426
427
428
429
430
431
432 public PrefixedProperties(final PrefixedProperties props, final String defaultPrefix) {
433 properties = props;
434 setDefaultPrefix(defaultPrefix);
435 }
436
437
438
439
440
441
442
443 public PrefixedProperties(final Properties defaults) {
444 properties = defaults instanceof PrefixedProperties ? defaults : new TrieMap<Object>().asProperties(defaults);
445 }
446
447
448
449
450
451
452
453 public PrefixedProperties(final String defaultPrefix) {
454 setDefaultPrefix(defaultPrefix);
455 }
456
457 private String checkAndConvertPrefix(final String prefix) {
458 if (prefix == null) {
459 throw new IllegalArgumentException("The prefix has to be set and is not allowed to be null.");
460 }
461 String myPrefix = prefix;
462 if ("*".equals(prefix)) {
463 myPrefix = StringUtils.repeat(PrefixConfig.PREFIXDELIMITER_STRING, getPrefixConfigs().size());
464 }
465 return myPrefix;
466 }
467
468
469
470
471
472
473 @Override
474 public void clear() {
475 lock.writeLock().lock();
476 try {
477 properties.clear();
478 } finally {
479 lock.writeLock().unlock();
480 }
481 }
482
483
484
485
486 public void clearDefaultPrefixes() {
487 final Map<Integer, PrefixConfig> prefixConfigs = getPrefixConfigs();
488 for (final PrefixConfig config : prefixConfigs.values()) {
489 config.setDefaultPrefix(null);
490 }
491 }
492
493
494
495
496 public void clearLocalPrefixes() {
497 final Map<Integer, PrefixConfig> prefixConfigs = getPrefixConfigs();
498 for (final PrefixConfig config : prefixConfigs.values()) {
499 config.setPrefix(null);
500 }
501 }
502
503
504
505
506
507
508 @SuppressWarnings("rawtypes")
509 @Override
510 public PrefixedProperties clone() {
511 lock.readLock().lock();
512 try {
513 final PrefixedProperties clone = (PrefixedProperties) super.clone();
514 if (prefixes != null) {
515 clone.prefixes = prefixes.clone();
516 }
517 if (properties instanceof PrefixedProperties) {
518 clone.properties = (Properties) properties.clone();
519 } else if (properties instanceof TrieMapBackedProperties) {
520 clone.properties = ((TrieMapBackedProperties) properties).clone();
521 } else {
522 clone.properties = new TrieMap<Object>().asProperties();
523 clone.properties.putAll(properties);
524 }
525 return clone;
526 } finally {
527 lock.readLock().unlock();
528 }
529 }
530
531 private void configureJsonParser(final JsonParser jp) {
532 jp.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
533 jp.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
534 jp.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
535 jp.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
536 }
537
538
539
540
541
542
543 @Override
544 public boolean contains(final Object value) {
545 lock.readLock().lock();
546 try {
547 if (value == null) {
548 return false;
549 }
550 for (@SuppressWarnings("rawtypes")
551 final Map.Entry entry : entrySet()) {
552 final Object otherValue = entry.getValue();
553 if (otherValue != null && otherValue.equals(value)) {
554 return true;
555 }
556 }
557 return false;
558 } finally {
559 lock.readLock().unlock();
560 }
561 }
562
563
564
565
566
567
568 @Override
569 public boolean containsKey(final Object key) {
570 lock.readLock().lock();
571 try {
572 if (isKeyValid(key)) {
573 final boolean useLocalPrefixes = !mixDefaultAndLocalPrefixes && hasLocalPrefixConfigurations();
574 if (!properties.containsKey(getPrefixedKey(key, useLocalPrefixes))) {
575 return properties.containsKey(key);
576 } else {
577 return true;
578 }
579 }
580 return false;
581 } finally {
582 lock.readLock().unlock();
583 }
584 }
585
586 private boolean containsValidPrefix(final Object key) {
587 if (key != null && String.class == key.getClass()) {
588 return prefixes.containsValidPrefix((String) key);
589 }
590 return false;
591 }
592
593
594
595
596
597
598 @Override
599 public boolean containsValue(final Object value) {
600 lock.readLock().lock();
601 try {
602 return contains(value);
603 } finally {
604 lock.readLock().unlock();
605 }
606 }
607
608
609
610
611
612
613 @SuppressWarnings({ "rawtypes", "unchecked" })
614 @Override
615 public PrefixedPropertiesEnumeration<Object> elements() {
616 lock.readLock().lock();
617 try {
618 final Collection values = values();
619 final Iterator it = values.iterator();
620 return new PrefixedPropertiesEnumerationImpl(it);
621 } finally {
622 lock.readLock().unlock();
623 }
624 }
625
626
627
628
629
630
631 @Override
632 public Set<Entry<Object, Object>> entrySet() {
633 final Set<Entry<Object, Object>> entrySet = new HashSet<Entry<Object, Object>>();
634 lock.readLock().lock();
635 try {
636 final boolean useLocalPrefixes = !mixDefaultAndLocalPrefixes && hasLocalPrefixConfigurations();
637 for (final Map.Entry<Object, Object> keyEntry : getKeyMap(false).entrySet()) {
638 final Object value = get(keyEntry.getValue(), useLocalPrefixes);
639 if (String.class == keyEntry.getKey().getClass()) {
640 entrySet.add(new PPEntry(keyEntry.getKey(), value));
641 } else {
642 entrySet.add(new PPEntry(keyEntry.getKey(), value));
643 }
644 }
645 return entrySet;
646 } finally {
647 lock.readLock().unlock();
648 }
649 }
650
651
652
653
654
655
656 @Override
657 public boolean equals(final Object obj) {
658 if (this == obj) {
659 return true;
660 }
661 if (!super.equals(obj)) {
662 return false;
663 }
664 if (getClass() != obj.getClass()) {
665 return false;
666 }
667 final PrefixedProperties other = (PrefixedProperties) obj;
668 if (prefixes == null) {
669 if (other.prefixes != null) {
670 return false;
671 }
672 } else if (!prefixes.equals(other.prefixes)) {
673 return false;
674 }
675 if (properties == null) {
676 if (other.properties != null) {
677 return false;
678 }
679 } else if (!properties.equals(other.properties)) {
680 return false;
681 }
682 return true;
683 }
684
685
686
687
688
689
690 @Override
691 public Object get(final Object key) {
692 final boolean useLocalPrefixes = !mixDefaultAndLocalPrefixes && hasLocalPrefixConfigurations();
693 return get(key, useLocalPrefixes);
694 }
695
696
697
698
699
700
701 protected Object get(final Object key, final boolean useLocalPrefixes) {
702 Object result = null;
703 lock.readLock().lock();
704 try {
705 final Object prefixedKey = getPrefixedKey(key, useLocalPrefixes);
706 result = (properties instanceof PrefixedProperties)
707 ? ((PrefixedProperties) properties).get(prefixedKey, useLocalPrefixes)
708 : properties.get(prefixedKey);
709
710 if (result == null) {
711 result = (properties instanceof PrefixedProperties)
712 ? ((PrefixedProperties) properties).get(key, useLocalPrefixes) : properties.get(key);
713 }
714 return result;
715 } finally {
716 lock.readLock().unlock();
717 }
718 }
719
720
721
722
723
724
725
726
727
728
729 public String[] getArray(final String key) {
730 final String value = getProperty(key);
731 if (value != null) {
732 final String[] strings = value.split(",[\\s]*|[\\s]*$");
733 return strings;
734 }
735 return null;
736 }
737
738
739
740
741
742
743
744
745
746
747
748
749
750 public String[] getArray(final String key, final String[] def) {
751 final String[] value = getArray(key);
752 if (value != null) {
753 return value;
754 }
755 return def;
756 }
757
758
759
760
761
762
763
764
765
766
767 public boolean getBoolean(final String key) {
768 return Boolean.valueOf(getProperty(key)).booleanValue();
769 }
770
771
772
773
774
775
776
777
778
779
780
781 public boolean getBoolean(final String key, final boolean def) {
782 final String value = getProperty(key);
783 return value != null ? Boolean.valueOf(value).booleanValue() : def;
784 }
785
786
787
788
789
790
791
792
793
794 public boolean[] getBooleanArray(final String key) {
795 final String[] value = getArray(key);
796 if (value != null) {
797 final boolean[] result = new boolean[value.length];
798 for (int i = 0; i < value.length; i++) {
799 result[i] = Boolean.valueOf(value[i]).booleanValue();
800 }
801 return result;
802 }
803 return null;
804 }
805
806
807
808
809
810
811
812
813
814
815
816
817
818 public boolean[] getBooleanArray(final String key, final boolean[] def) {
819 final boolean[] result = getBooleanArray(key);
820 return result == null ? def : result;
821 }
822
823
824
825
826
827
828
829
830 public byte getByte(final String key) {
831 final String value = getProperty(key);
832 if (value == null) {
833 throw new NumberFormatException("Couldn't parse property to byte.");
834 }
835 return Byte.parseByte(value);
836 }
837
838
839
840
841
842
843
844
845
846
847
848 public byte getByte(final String key, final byte def) {
849 try {
850 return getByte(key);
851 } catch (final NumberFormatException nfe) {
852 return def;
853 }
854 }
855
856
857
858
859
860
861
862
863 public byte[] getByteArray(final String key) {
864 final String[] value = getArray(key);
865 if (value != null) {
866 final byte[] result = new byte[value.length];
867 for (int i = 0; i < value.length; i++) {
868 result[i] = Byte.parseByte(value[i]);
869 }
870 return result;
871 }
872 return null;
873 }
874
875
876
877
878
879
880
881
882
883
884 public byte[] getByteArray(final String key, final byte[] def) {
885 try {
886 final byte[] result = getByteArray(key);
887 return result != null ? result : def;
888 } catch (final NumberFormatException nfe) {
889 return def;
890 }
891 }
892
893
894
895
896
897
898 protected Properties getCompleteProperties() {
899 if (properties instanceof PrefixedProperties) {
900 return ((PrefixedProperties) properties).getCompleteProperties();
901 } else {
902 return properties;
903 }
904 }
905
906
907
908
909
910
911
912
913 public double getDouble(final String key) {
914 final String value = getProperty(key);
915 if (value == null) {
916 throw new NumberFormatException("Couldn't parse property to double.");
917 }
918 return Double.parseDouble(value);
919 }
920
921
922
923
924
925
926
927
928
929
930
931 public double getDouble(final String key, final double def) {
932 try {
933 return getDouble(key);
934 } catch (final NumberFormatException nfe) {
935 return def;
936 }
937 }
938
939
940
941
942
943
944
945
946
947 public double[] getDoubleArray(final String key) {
948 final String[] value = getArray(key);
949 if (value != null) {
950 final double[] result = new double[value.length];
951 for (int i = 0; i < value.length; i++) {
952 result[i] = Double.parseDouble(value[i]);
953 }
954 return result;
955 }
956 return null;
957 }
958
959
960
961
962
963
964
965
966
967
968
969
970
971 public double[] getDoubleArray(final String key, final double[] def) {
972 try {
973 final double[] result = getDoubleArray(key);
974 return result != null ? result : def;
975 } catch (final NumberFormatException nfe) {
976 return def;
977 }
978 }
979
980
981
982
983
984
985 public String getEffectivePrefix() {
986 lock.readLock().lock();
987 try {
988 final boolean useLocalPrefixes = !mixDefaultAndLocalPrefixes && hasLocalPrefixConfigurations();
989 return getPrefix(new StringBuilder(), useLocalPrefixes).toString();
990 } finally {
991 lock.readLock().unlock();
992 }
993 }
994
995
996
997
998
999
1000
1001
1002 public float getFloat(final String key) {
1003 final String value = getProperty(key);
1004 if (value == null) {
1005 throw new NumberFormatException("Couldn't parse property to float.");
1006 }
1007 return Float.parseFloat(value);
1008 }
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 public float getFloat(final String key, final float def) {
1021 try {
1022 return getFloat(key);
1023 } catch (final NumberFormatException nfe) {
1024 return def;
1025 }
1026 }
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036 public float[] getFloatArray(final String key) {
1037 final String[] value = getArray(key);
1038 if (value != null) {
1039 final float[] result = new float[value.length];
1040 for (int i = 0; i < value.length; i++) {
1041 result[i] = Float.parseFloat(value[i]);
1042 }
1043 return result;
1044 }
1045 return null;
1046 }
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060 public float[] getFloatArray(final String key, final float[] def) {
1061 try {
1062 final float[] result = getFloatArray(key);
1063 return result != null ? result : def;
1064 } catch (final NumberFormatException nfe) {
1065 return def;
1066 }
1067 }
1068
1069
1070
1071
1072
1073
1074
1075
1076 public int getInt(final String key) {
1077 final String value = getProperty(key);
1078 if (value == null) {
1079 throw new NumberFormatException("Couldn't parse property to int.");
1080 }
1081 return Integer.parseInt(value);
1082 }
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095 public int getInt(final String key, final int def) {
1096 try {
1097 return getInt(key);
1098 } catch (final NumberFormatException nfe) {
1099 return def;
1100 }
1101 }
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111 public int[] getIntArray(final String key) {
1112 final String[] value = getArray(key);
1113 if (value != null) {
1114 final int[] result = new int[value.length];
1115 for (int i = 0; i < value.length; i++) {
1116 result[i] = Integer.parseInt(value[i]);
1117 }
1118 return result;
1119 }
1120 return null;
1121 }
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135 public int[] getIntArray(final String key, final int[] def) {
1136 try {
1137 final int[] result = getIntArray(key);
1138 return result != null ? result : def;
1139 } catch (final NumberFormatException nfe) {
1140 return def;
1141 }
1142 }
1143
1144 private Map<Object, Object> getKeyMap(final boolean onlyStrings) {
1145 final Map<Object, Object> result = new HashMap<Object, Object>();
1146 for (@SuppressWarnings("rawtypes")
1147 final Map.Entry entry : properties.entrySet()) {
1148 if (String.class == entry.getKey().getClass()) {
1149 if (isKeyValid(entry.getKey())) {
1150 final Object unprefixedKey = getUnprefixedKey(entry.getKey());
1151 if (result.containsKey(unprefixedKey)) {
1152 if (!unprefixedKey.equals(entry.getKey())) {
1153 result.put(unprefixedKey, entry.getKey());
1154 }
1155 } else {
1156 result.put(unprefixedKey, entry.getKey());
1157 }
1158 }
1159 } else if (!onlyStrings) {
1160 result.put(entry.getKey(), entry.getKey());
1161 }
1162 }
1163 return result;
1164 }
1165
1166
1167
1168
1169
1170
1171
1172
1173 public long getLong(final String key) {
1174 final String value = getProperty(key);
1175 if (value == null) {
1176 throw new NumberFormatException("Couldn't parse property to long.");
1177 }
1178 return Long.parseLong(value);
1179 }
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191 public long getLong(final String key, final long def) {
1192 try {
1193 return getLong(key);
1194 } catch (final NumberFormatException nfe) {
1195 return def;
1196 }
1197 }
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207 public long[] getLongArray(final String key) {
1208 final String[] value = getArray(key);
1209 if (value != null) {
1210 final long[] result = new long[value.length];
1211 for (int i = 0; i < value.length; i++) {
1212 result[i] = Long.parseLong(value[i]);
1213 }
1214 return result;
1215 }
1216 return null;
1217 }
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231 public long[] getLongArray(final String key, final long[] def) {
1232 try {
1233 final long[] result = getLongArray(key);
1234 return result != null ? result : def;
1235 } catch (final NumberFormatException nfe) {
1236 return def;
1237 }
1238 }
1239
1240 private StringBuilder getPrefix(final StringBuilder sb, final boolean useLocalPrefixConfigurations) {
1241 if (properties instanceof PrefixedProperties) {
1242 ((PrefixedProperties) properties).getPrefix(sb, useLocalPrefixConfigurations);
1243 }
1244
1245 if (prefixes != null) {
1246 if (!useLocalPrefixConfigurations) {
1247 if (prefixes.getPrefix() != null) {
1248 if (sb.length() > 0) {
1249 sb.append(PrefixConfig.PREFIXDELIMITER);
1250 }
1251 sb.append(prefixes.getPrefix());
1252 }
1253 } else {
1254 if (prefixes.getLocalPrefix() != null) {
1255 if (sb.length() > 0) {
1256 sb.append(PrefixConfig.PREFIXDELIMITER);
1257 }
1258 sb.append(prefixes.getLocalPrefix());
1259 }
1260 }
1261 }
1262 return sb;
1263 }
1264
1265
1266
1267
1268
1269
1270 public PrefixConfig getPrefixConfig() {
1271 lock.readLock().lock();
1272 try {
1273 return prefixes;
1274 } finally {
1275 lock.readLock().unlock();
1276 }
1277 }
1278
1279 private Map<Integer, PrefixConfig> getPrefixConfigs() {
1280 return getPrefixConfigs(new TreeMap<Integer, PrefixConfig>());
1281 }
1282
1283 private Map<Integer, PrefixConfig> getPrefixConfigs(final Map<Integer, PrefixConfig> result) {
1284 if (properties instanceof PrefixedProperties) {
1285 ((PrefixedProperties) properties).getPrefixConfigs(result);
1286 }
1287 result.put(result.size(), getPrefixConfig());
1288 return result;
1289 }
1290
1291 @SuppressWarnings("unchecked")
1292 private <T> T getPrefixedKey(final T key, final boolean useLocalPrefixConfigurations) {
1293 if (String.class == key.getClass()) {
1294 if (containsValidPrefix(key)) {
1295 return key;
1296 } else {
1297 if (prefixes != null) {
1298 return (T) prefixes.getPrefixedKey((String) key, useLocalPrefixConfigurations);
1299 } else {
1300 return key;
1301 }
1302 }
1303 }
1304 return key;
1305 }
1306
1307 private Set<String> getPrefixes() {
1308 return prefixes != null ? prefixes.getPrefixes() : Collections.<String> emptySet();
1309 }
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321 @Override
1322 public String getProperty(final String key) {
1323 lock.readLock().lock();
1324 try {
1325 final boolean useLocalPrefixes = !mixDefaultAndLocalPrefixes && hasLocalPrefixConfigurations();
1326 final Object object = get(key, useLocalPrefixes);
1327 if (object instanceof String) {
1328 return (String) object;
1329 } else {
1330 if (object == null) {
1331 return null;
1332 }
1333 throw new IllegalStateException("The value of " + key + " is of type: " + object.getClass().getName());
1334 }
1335 } finally {
1336 lock.readLock().unlock();
1337 }
1338 }
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351 @Override
1352 public String getProperty(final String value, final String def) {
1353 final String result = getProperty(value);
1354 return result == null ? def : result;
1355 }
1356
1357
1358
1359
1360
1361
1362
1363
1364 public short getShort(final String key) {
1365 final String value = getProperty(key);
1366 if (value == null) {
1367 throw new NumberFormatException("Couldn't parse property to short.");
1368 }
1369 return Short.parseShort(value);
1370 }
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382 public short getShort(final String key, final short def) {
1383 try {
1384 return getShort(key);
1385 } catch (final NumberFormatException nfe) {
1386 return def;
1387 }
1388 }
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398 public short[] getShortArray(final String key) {
1399 final String[] value = getArray(key);
1400 if (value != null) {
1401 final short[] result = new short[value.length];
1402 for (int i = 0; i < value.length; i++) {
1403 result[i] = Short.parseShort(value[i]);
1404 }
1405 return result;
1406 }
1407 return null;
1408 }
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422 public short[] getShortArray(final String key, final short[] def) {
1423 try {
1424 final short[] result = getShortArray(key);
1425 return result != null ? result : def;
1426 } catch (final NumberFormatException nfe) {
1427 return def;
1428 }
1429 }
1430
1431 private List<DoubleEntry<PrefixConfig, String>> getToSetPrefixMap(final List<String> prefixesList,
1432 final Map<Integer, PrefixConfig> configs) throws IllegalArgumentException {
1433 int i = 0;
1434 PrefixConfig config = null;
1435 final Map<Integer, PrefixConfig> subConfigs = new HashMap<Integer, PrefixConfig>(configs);
1436 final List<DoubleEntry<PrefixConfig, String>> result = new LinkedList<DoubleEntry<PrefixConfig, String>>();
1437 for (final Map.Entry<Integer, PrefixConfig> entry : configs.entrySet()) {
1438 if (i == prefixesList.size()) {
1439 break;
1440 }
1441 config = entry.getValue();
1442 subConfigs.remove(entry.getKey());
1443 if (config.isDynamic()) {
1444 try {
1445 result.addAll(getToSetPrefixMap(prefixesList.subList(i, prefixesList.size()), subConfigs));
1446 i = prefixesList.size();
1447 break;
1448 } catch (final IllegalArgumentException iae) {
1449 result.add(new DoubleEntry<PrefixConfig, String>(config, prefixesList.get(i)));
1450 i++;
1451 }
1452 } else if (config.containsValidPrefix(prefixesList.get(i))) {
1453 result.add(new DoubleEntry<PrefixConfig, String>(config, prefixesList.get(i)));
1454 i++;
1455 }
1456 }
1457 if (i < prefixesList.size()) {
1458 throw new IllegalArgumentException("Prefix does not match the given PrefixConfig.");
1459 }
1460 return result;
1461 }
1462
1463 @SuppressWarnings("unchecked")
1464 private Map<String, Object> getTreeMap() {
1465 final Map<Integer, PrefixConfig> configs = getPrefixConfigs();
1466 final Map<String, Object> treeMap = new TreeMap<String, Object>();
1467 final Properties props = getCompleteProperties();
1468 String keyName = "";
1469 String plainProperty = "";
1470 for (final Enumeration<?> completition = props.propertyNames(); completition.hasMoreElements();) {
1471 keyName = (String) completition.nextElement();
1472 plainProperty = keyName;
1473 Map<String, Object> propertyMap = treeMap;
1474 for (int i = 0; i < configs.size(); i++) {
1475 final PrefixConfig config = configs.get(i);
1476 boolean found = false;
1477 for (final Iterator<String> prefixIterator = config.getPrefixes().iterator(); prefixIterator.hasNext()
1478 && !found;) {
1479 final String prefix = prefixIterator.next();
1480 if (plainProperty.startsWith(prefix + PrefixConfig.PREFIXDELIMITER)) {
1481 Object subMap = propertyMap.get(prefix);
1482 if (subMap == null) {
1483 subMap = new TreeMap<String, Object>();
1484 propertyMap.put(prefix, subMap);
1485 }
1486 plainProperty = plainProperty.replaceFirst(prefix + PrefixConfig.PREFIXDELIMITER, "");
1487 found = true;
1488 if (subMap instanceof Map<?, ?>) {
1489 propertyMap = (Map<String, Object>) subMap;
1490 } else {
1491 throw new IllegalStateException("Failed to render JSON-File.");
1492 }
1493 }
1494 }
1495 }
1496 propertyMap.put((char) 1 + plainProperty, props.getProperty(keyName));
1497 }
1498 return treeMap;
1499 }
1500
1501 @SuppressWarnings("unchecked")
1502 private <T> T getUnprefixedKey(final T key) {
1503 if (key == null) {
1504 throw new IllegalArgumentException("A null key is not allowed.");
1505 }
1506 if (String.class == key.getClass()) {
1507 String newKey = (String) key;
1508 if (properties instanceof PrefixedProperties) {
1509 newKey = (String) ((PrefixedProperties) properties).getUnprefixedKey(key);
1510 }
1511 newKey = prefixes.getUnprefixedKey(newKey);
1512 return (T) newKey;
1513 }
1514 return key;
1515 }
1516
1517
1518
1519
1520
1521
1522 @Override
1523 public int hashCode() {
1524 final int prime = 31;
1525 int result = super.hashCode();
1526 result = prime * result + (prefixes == null ? 0 : prefixes.hashCode());
1527 result = prime * result + (properties == null ? 0 : properties.hashCode());
1528 return result;
1529 }
1530
1531
1532
1533
1534
1535
1536 public boolean hasLocalPrefixConfigurations() {
1537 return prefixes.containsLocalPrefix() || ((properties instanceof PrefixedProperties)
1538 && ((PrefixedProperties) properties).hasLocalPrefixConfigurations());
1539 }
1540
1541
1542
1543
1544
1545
1546 @Override
1547 public boolean isEmpty() {
1548 lock.readLock().lock();
1549 try {
1550 return entrySet().isEmpty();
1551 } finally {
1552 lock.readLock().unlock();
1553 }
1554 }
1555
1556 private boolean isKeyValid(final Object key) {
1557 if (key == null) {
1558 throw new IllegalArgumentException("A null key is not allowed.");
1559 }
1560 if (String.class == key.getClass()) {
1561 return !containsValidPrefix(key) || startsWithCurrentPrefix(key);
1562 }
1563 return true;
1564 }
1565
1566
1567
1568
1569
1570
1571 @SuppressWarnings("unchecked")
1572 @Override
1573 public PrefixedPropertiesEnumeration<Object> keys() {
1574 lock.readLock().lock();
1575 try {
1576 @SuppressWarnings("rawtypes")
1577 final Set keys = keySet();
1578 @SuppressWarnings("rawtypes")
1579 final Iterator it = keys.iterator();
1580 return new PrefixedPropertiesEnumerationImpl<Object>(it, true);
1581 } finally {
1582 lock.readLock().unlock();
1583 }
1584 }
1585
1586
1587
1588
1589
1590
1591 @SuppressWarnings({ "rawtypes", "unchecked" })
1592 @Override
1593 public Set<Object> keySet() {
1594 return new HashSet(getKeyMap(false).keySet());
1595 }
1596
1597
1598
1599
1600
1601
1602 @Override
1603 public void list(final PrintStream out) {
1604 lock.readLock().lock();
1605 try {
1606 properties.list(out);
1607 } finally {
1608 lock.readLock().unlock();
1609 }
1610 }
1611
1612
1613
1614
1615
1616
1617 @Override
1618 public void list(final PrintWriter out) {
1619 lock.readLock().lock();
1620 try {
1621 properties.list(out);
1622 } finally {
1623 lock.readLock().unlock();
1624 }
1625 }
1626
1627
1628
1629
1630
1631
1632 @Override
1633 public void load(final InputStream inStream) throws IOException {
1634 lock.writeLock().lock();
1635 try {
1636 properties.load(inStream);
1637 } finally {
1638 lock.writeLock().unlock();
1639 }
1640 }
1641
1642
1643
1644
1645
1646
1647 @Override
1648 public void load(final Reader reader) throws IOException {
1649 lock.writeLock().lock();
1650 try {
1651 properties.load(reader);
1652 } finally {
1653 lock.writeLock().unlock();
1654 }
1655 }
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666 public void loadFromJSON(final InputStream is) throws IOException {
1667 lock.writeLock().lock();
1668 try {
1669 final JsonFactory f = new JsonFactory();
1670 final JsonParser jp = f.createParser(is);
1671 configureJsonParser(jp);
1672 if (jp.nextToken() == JsonToken.START_OBJECT) {
1673 traverseJSON(jp, null);
1674 }
1675 } finally {
1676 lock.writeLock().unlock();
1677 }
1678 }
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689 public void loadFromJSON(final Reader reader) throws IOException {
1690 lock.writeLock().lock();
1691 try {
1692 final JsonFactory f = new JsonFactory();
1693 final JsonParser jp = f.createParser(reader);
1694 configureJsonParser(jp);
1695 if (jp.nextToken() == JsonToken.START_OBJECT) {
1696 traverseJSON(jp, null);
1697 }
1698 } finally {
1699 lock.writeLock().unlock();
1700 }
1701 }
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712 public void loadFromYAML(final InputStream is) throws IOException {
1713 lock.writeLock().lock();
1714 try {
1715 final YAMLFactory f = new YAMLFactory();
1716 final YAMLParser jp = f.createParser(is);
1717 configureJsonParser(jp);
1718 if (jp.nextToken() == JsonToken.START_OBJECT) {
1719 traverseJSON(jp, null);
1720 }
1721 } finally {
1722 lock.writeLock().unlock();
1723 }
1724 }
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735 public void loadFromYAML(final Reader reader) throws IOException {
1736 lock.writeLock().lock();
1737 try {
1738 final YAMLFactory f = new YAMLFactory();
1739 final JsonParser jp = f.createParser(reader);
1740 configureJsonParser(jp);
1741 if (jp.nextToken() == JsonToken.START_OBJECT) {
1742 traverseJSON(jp, null);
1743 }
1744 } finally {
1745 lock.writeLock().unlock();
1746 }
1747 }
1748
1749
1750
1751
1752
1753
1754 @Override
1755 public void loadFromXML(final InputStream in) throws IOException {
1756 lock.writeLock().lock();
1757 try {
1758 properties.loadFromXML(in);
1759 } finally {
1760 lock.writeLock().unlock();
1761 }
1762 }
1763
1764
1765
1766
1767
1768
1769 @SuppressWarnings({ "rawtypes", "unchecked" })
1770 @Override
1771 public PrefixedPropertiesEnumeration<?> propertyNames() {
1772 lock.readLock().lock();
1773 try {
1774 final Set result = new HashSet();
1775 for (final Object key : getKeyMap(false).keySet()) {
1776 result.add(getUnprefixedKey(key));
1777 }
1778 return new PrefixedPropertiesEnumerationImpl(result.iterator(), true);
1779 } finally {
1780 lock.readLock().unlock();
1781 }
1782 }
1783
1784
1785
1786
1787
1788
1789 @Override
1790 public Object put(final Object key, final Object value) {
1791 lock.writeLock().lock();
1792 try {
1793 return properties.put(key, value);
1794 } finally {
1795 lock.writeLock().unlock();
1796 }
1797 }
1798
1799
1800
1801
1802
1803
1804 @Override
1805 public void putAll(final Map<? extends Object, ? extends Object> t) {
1806 lock.writeLock().lock();
1807 try {
1808 properties.putAll(t);
1809 } finally {
1810 lock.writeLock().unlock();
1811 }
1812 }
1813
1814 private void readObject(final ObjectInputStream ois) throws ClassNotFoundException, IOException {
1815 prefixes = (PrefixConfig) ois.readObject();
1816 properties = (Properties) ois.readObject();
1817 mixDefaultAndLocalPrefixes = ois.readBoolean();
1818 lock = new ReentrantReadWriteLock();
1819 }
1820
1821
1822
1823
1824
1825
1826 @Override
1827 public Object remove(final Object key) {
1828 lock.writeLock().lock();
1829 try {
1830 final boolean useLocalPrefixes = !mixDefaultAndLocalPrefixes && hasLocalPrefixConfigurations();
1831 final Object someKey = getPrefixedKey(key, useLocalPrefixes);
1832 Object result = properties.remove(someKey);
1833 if (result == null) {
1834 result = properties.remove(key);
1835 }
1836 return result;
1837 } finally {
1838 lock.writeLock().unlock();
1839 }
1840 }
1841
1842
1843
1844
1845
1846
1847
1848
1849 public Map<Object, Object> removeAll(final Object key) {
1850 lock.writeLock().lock();
1851 try {
1852 final Map<Object, Object> result = new HashMap<Object, Object>();
1853 Object resultObj;
1854 if (containsValidPrefix(key)) {
1855 resultObj = properties.remove(key);
1856 if (resultObj != null) {
1857 result.put(key, resultObj);
1858 }
1859 } else {
1860 for (final String prefix : getPrefixes()) {
1861 final String pkey = prefix + PrefixConfig.PREFIXDELIMITER + key;
1862 resultObj = properties.remove(pkey);
1863 if (resultObj != null) {
1864 result.put(pkey, resultObj);
1865 }
1866 }
1867 resultObj = properties.remove(key);
1868 if (resultObj != null) {
1869 result.put(key, resultObj);
1870 }
1871 }
1872 return result;
1873 } finally {
1874 lock.writeLock().unlock();
1875 }
1876 }
1877
1878
1879
1880
1881
1882
1883
1884
1885 public void removeProperty(final String key) {
1886 remove(key);
1887 }
1888
1889
1890
1891
1892
1893
1894 @SuppressWarnings("deprecation")
1895 @Override
1896 public void save(final OutputStream out, final String comments) {
1897 lock.readLock().lock();
1898 try {
1899 properties.save(out, comments);
1900 } finally {
1901 lock.readLock().unlock();
1902 }
1903 }
1904
1905
1906
1907
1908
1909
1910
1911 public void setDefaultPrefix(final String prefix) {
1912 lock.writeLock().lock();
1913 try {
1914 final String myPrefix = checkAndConvertPrefix(prefix);
1915 final List<String> prefixList = split(myPrefix);
1916 setDefaultPrefixes(prefixList);
1917 } finally {
1918 lock.writeLock().unlock();
1919 }
1920 }
1921
1922 private void setDefaultPrefixes(final List<String> prefixesList) {
1923 final Map<Integer, PrefixConfig> configs = getPrefixConfigs();
1924 try {
1925 final List<DoubleEntry<PrefixConfig, String>> prefixesToSet = getToSetPrefixMap(prefixesList, configs);
1926 final List<PrefixConfig> prefixesToSetList = new ArrayList<PrefixConfig>();
1927 for (final DoubleEntry<PrefixConfig, String> entry : prefixesToSet) {
1928 entry.getOne().setDefaultPrefix(entry.getTwo());
1929 prefixesToSetList.add(entry.getOne());
1930 }
1931 final Collection<PrefixConfig> allConfigs = getPrefixConfigs().values();
1932 for (final PrefixConfig config : allConfigs) {
1933 if (!prefixesToSetList.contains(config)) {
1934 config.setDefaultPrefix(null);
1935
1936 }
1937 }
1938 } catch (final IllegalArgumentException iae) {
1939 throw new IllegalArgumentException("The given prefixes are not part of the PrefixConfig: " + prefixesList);
1940 }
1941 }
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951 public void setLocalPrefix(final String configuredPrefix) {
1952 lock.writeLock().lock();
1953 try {
1954 final String myPrefix = checkAndConvertPrefix(configuredPrefix);
1955 final List<String> prefixList = split(myPrefix);
1956 setPrefixes(prefixList);
1957 } finally {
1958 lock.writeLock().unlock();
1959 }
1960 }
1961
1962
1963
1964
1965
1966
1967 public void setMixDefaultAndLocalPrefixSettings(final boolean value) {
1968 this.mixDefaultAndLocalPrefixes = value;
1969 if (properties instanceof PrefixedProperties) {
1970 ((PrefixedProperties) properties).setMixDefaultAndLocalPrefixSettings(value);
1971 }
1972 }
1973
1974
1975
1976
1977
1978
1979
1980 public void setPrefixConfig(final PrefixConfig config) {
1981 lock.writeLock().lock();
1982 try {
1983 if (config == null) {
1984 prefixes = EmptyPrefix.INSTANCE;
1985 } else {
1986 prefixes = config;
1987 }
1988 } finally {
1989 lock.writeLock().unlock();
1990 }
1991 }
1992
1993 private void setPrefixes(final List<String> prefixesList) {
1994 final Map<Integer, PrefixConfig> configs = getPrefixConfigs();
1995 try {
1996 final List<DoubleEntry<PrefixConfig, String>> prefixesToSet = getToSetPrefixMap(prefixesList, configs);
1997 final List<PrefixConfig> prefixesToSetList = new ArrayList<PrefixConfig>();
1998 for (final DoubleEntry<PrefixConfig, String> entry : prefixesToSet) {
1999 entry.getOne().setPrefix(entry.getTwo());
2000 prefixesToSetList.add(entry.getOne());
2001 }
2002 final Collection<PrefixConfig> allConfigs = getPrefixConfigs().values();
2003 for (final PrefixConfig config : allConfigs) {
2004 if (!prefixesToSetList.contains(config)) {
2005 config.setPrefix(null);
2006
2007 }
2008 }
2009 } catch (final IllegalArgumentException iae) {
2010 throw new IllegalArgumentException("The given prefixes are not part of the PrefixConfig: " + prefixesList);
2011 }
2012 }
2013
2014
2015
2016
2017
2018
2019 @Override
2020 public Object setProperty(final String key, final String value) {
2021 lock.writeLock().lock();
2022 try {
2023 return properties.setProperty(key, value);
2024 } finally {
2025 lock.writeLock().unlock();
2026 }
2027 }
2028
2029
2030
2031
2032
2033
2034 @Override
2035 public int size() {
2036 lock.readLock().lock();
2037 try {
2038 return getKeyMap(false).size();
2039 } finally {
2040 lock.readLock().unlock();
2041 }
2042 }
2043
2044 private List<String> split(final String myPrefix) {
2045 List<String> prefixList;
2046 if (myPrefix.indexOf(PrefixConfig.PREFIXDELIMITER) != -1) {
2047 prefixList = new ArrayList<String>(Arrays.asList(myPrefix.split("\\" + PrefixConfig.PREFIXDELIMITER)));
2048 } else {
2049 prefixList = new ArrayList<String>(1);
2050 prefixList.add(myPrefix);
2051 }
2052 return prefixList;
2053 }
2054
2055 private boolean startsWithCurrentPrefix(final Object key) {
2056 if (key != null && String.class == key.getClass()) {
2057 return prefixes.startsWithCurrentPrefix((String) key);
2058 }
2059 return false;
2060 }
2061
2062
2063
2064
2065
2066
2067 @Override
2068 public void store(final OutputStream out, final String comments) throws IOException {
2069 lock.readLock().lock();
2070 try {
2071 properties.store(out, comments);
2072 } finally {
2073 lock.readLock().unlock();
2074 }
2075 }
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089 public void store(final OutputStream out, final String comments, final String encoding) throws IOException {
2090 lock.readLock().lock();
2091 try {
2092 properties.store(new OutputStreamWriter(out, Charset.forName(encoding)), comments);
2093 } finally {
2094 lock.readLock().unlock();
2095 }
2096 }
2097
2098
2099
2100
2101
2102
2103 @Override
2104 public void store(final Writer writer, final String comments) throws IOException {
2105 lock.readLock().lock();
2106 try {
2107 properties.store(writer, comments);
2108 } finally {
2109 lock.readLock().unlock();
2110 }
2111 }
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121 public void storeToJSON(final OutputStream os) throws IOException {
2122 lock.readLock().lock();
2123 try {
2124 final JsonFactory f = new JsonFactory();
2125 final JsonGenerator generator = f.createGenerator(os, JsonEncoding.UTF8);
2126
2127 generator.useDefaultPrettyPrinter();
2128
2129 generator.writeStartObject();
2130 writeJsonOrYaml(generator, getTreeMap());
2131 generator.writeEndObject();
2132 generator.flush();
2133 } finally {
2134 lock.readLock().unlock();
2135 }
2136 }
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149 public void storeToJSON(final OutputStream os, final String header) throws IOException {
2150 storeToJSON(os, header, "UTF-8");
2151 }
2152
2153 public void storeToJSON(final OutputStream os, final String header, final String encoding) throws IOException {
2154 lock.readLock().lock();
2155 try {
2156 final JsonFactory f = new JsonFactory();
2157 final JsonGenerator generator = f.createGenerator(new OutputStreamWriter(os, Charset.forName(encoding)));
2158 generator.useDefaultPrettyPrinter();
2159
2160 generator.writeStartObject();
2161 if (header != null) {
2162 generator.writeRaw("/*");
2163 generator.writeRaw(header);
2164 generator.writeRaw("*/");
2165 }
2166
2167 writeJsonOrYaml(generator, getTreeMap());
2168 generator.writeEndObject();
2169 generator.flush();
2170 } finally {
2171 lock.readLock().unlock();
2172 }
2173 }
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183 public void storeToYAML(final OutputStream os) throws IOException {
2184 lock.readLock().lock();
2185 try {
2186 final YAMLFactory f = new YAMLFactory();
2187 final YAMLGenerator generator = f.createGenerator(os, JsonEncoding.UTF8);
2188 generator.useDefaultPrettyPrinter();
2189
2190 generator.writeStartObject();
2191 writeJsonOrYaml(generator, getTreeMap());
2192 generator.writeEndObject();
2193 generator.flush();
2194 } finally {
2195 lock.readLock().unlock();
2196 }
2197 }
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210 public void storeToYAML(final OutputStream os, final String header) throws IOException {
2211 storeToYAML(os, header, "UTF-8");
2212 }
2213
2214 public void storeToYAML(final OutputStream os, final String header, final String encoding) throws IOException {
2215 lock.readLock().lock();
2216 try {
2217 final YAMLFactory f = new YAMLFactory();
2218 final JsonGenerator generator = f.createGenerator(new OutputStreamWriter(os, Charset.forName(encoding)));
2219 generator.useDefaultPrettyPrinter();
2220
2221 generator.writeStartObject();
2222 if (header != null) {
2223 generator.writeRaw("/*");
2224 generator.writeRaw(header);
2225 generator.writeRaw("*/");
2226 }
2227
2228 writeJsonOrYaml(generator, getTreeMap());
2229 generator.writeEndObject();
2230 generator.flush();
2231 } finally {
2232 lock.readLock().unlock();
2233 }
2234 }
2235
2236
2237
2238
2239
2240
2241
2242 @Override
2243 public void storeToXML(final OutputStream os, final String comment) throws IOException {
2244 lock.readLock().lock();
2245 try {
2246 properties.storeToXML(os, comment);
2247 } finally {
2248 lock.readLock().unlock();
2249 }
2250 }
2251
2252
2253
2254
2255
2256
2257
2258 @Override
2259 public void storeToXML(final OutputStream os, final String comment, final String encoding) throws IOException {
2260 lock.readLock().lock();
2261 try {
2262 properties.storeToXML(os, comment, encoding);
2263 } finally {
2264 lock.readLock().unlock();
2265 }
2266 }
2267
2268
2269
2270
2271
2272
2273 @Override
2274 public Set<String> stringPropertyNames() {
2275 lock.readLock().lock();
2276 try {
2277 final Set<String> result = new HashSet<String>();
2278 for (final Object key : getKeyMap(true).keySet()) {
2279 result.add(getUnprefixedKey((String) key));
2280 }
2281 return result;
2282 } finally {
2283 lock.readLock().unlock();
2284 }
2285 }
2286
2287
2288
2289
2290
2291
2292 @Override
2293 public String toString() {
2294 lock.readLock().lock();
2295 try {
2296 return properties.toString();
2297 } finally {
2298 lock.readLock().unlock();
2299 }
2300 }
2301
2302 protected void traverseJSON(final JsonParser jp, final String prefix) throws IOException {
2303 while (jp.nextToken() != JsonToken.END_OBJECT) {
2304 final String fieldname = jp.getText();
2305 if (jp.nextToken() == JsonToken.START_OBJECT) {
2306 traverseJSON(jp, prefix != null ? prefix + PrefixConfig.PREFIXDELIMITER + fieldname : fieldname);
2307 } else {
2308 final String text = jp.getText();
2309 put(prefix != null ? prefix + PrefixConfig.PREFIXDELIMITER + fieldname : fieldname, text);
2310 }
2311 }
2312 }
2313
2314
2315
2316
2317
2318
2319 @Override
2320 public Collection<Object> values() {
2321 lock.readLock().lock();
2322 try {
2323 final List<Object> result = new LinkedList<Object>();
2324 final boolean useLocalPrefixes = !mixDefaultAndLocalPrefixes && hasLocalPrefixConfigurations();
2325 for (final Object key : getKeyMap(false).values()) {
2326 result.add(get(key, useLocalPrefixes));
2327 }
2328 return result;
2329 } finally {
2330 lock.readLock().unlock();
2331 }
2332 }
2333
2334 @SuppressWarnings("unchecked")
2335 protected void writeJsonOrYaml(final JsonGenerator generator, final Map<String, Object> treeMap) throws IOException {
2336 if (treeMap != null) {
2337 for (final Map.Entry<String, Object> entry : treeMap.entrySet()) {
2338 if (entry.getValue() instanceof String) {
2339 generator.writeStringField(entry.getKey().substring(1), (String) entry.getValue());
2340 } else if (entry.getValue() instanceof Map<?, ?>) {
2341 generator.writeObjectFieldStart(entry.getKey());
2342 writeJsonOrYaml(generator, (Map<String, Object>) entry.getValue());
2343 generator.writeEndObject();
2344 }
2345 }
2346 }
2347 }
2348
2349 private void writeObject(final ObjectOutputStream oos) throws IOException {
2350 oos.writeObject(prefixes);
2351 oos.writeObject(properties);
2352 oos.writeBoolean(mixDefaultAndLocalPrefixes);
2353 }
2354
2355 }