32 import java.io.OutputStream;
33 import java.io.Reader;
34 import java.io.Writer;
35 import java.io.OutputStreamWriter;
36 import java.io.BufferedWriter;
37 import java.io.ObjectInputStream;
38 import java.io.ObjectOutputStream;
39 import java.io.StreamCorruptedException;
40 import java.io.UnsupportedEncodingException;
41 import java.nio.charset.Charset;
42 import java.nio.charset.IllegalCharsetNameException;
43 import java.nio.charset.UnsupportedCharsetException;
44 import java.util.concurrent.ConcurrentHashMap;
45 import java.util.function.BiConsumer;
46 import java.util.function.BiFunction;
47 import java.util.function.Function;
48
49 import jdk.internal.misc.SharedSecrets;
50 import jdk.internal.util.xml.PropertiesDefaultHandler;
51
52 /**
53 * The {@code Properties} class represents a persistent set of
54 * properties. The {@code Properties} can be saved to a stream
55 * or loaded from a stream. Each key and its corresponding value in
56 * the property list is a string.
57 * <p>
58 * A property list can contain another property list as its
59 * "defaults"; this second property list is searched if
60 * the property key is not found in the original property list.
61 * <p>
62 * Because {@code Properties} inherits from {@code Hashtable}, the
63 * {@code put} and {@code putAll} methods can be applied to a
64 * {@code Properties} object. Their use is strongly discouraged as they
65 * allow the caller to insert entries whose keys or values are not
66 * {@code Strings}. The {@code setProperty} method should be used
67 * instead. If the {@code store} or {@code save} method is called
68 * on a "compromised" {@code Properties} object that contains a
69 * non-{@code String} key or value, the call will fail. Similarly,
70 * the call to the {@code propertyNames} or {@code list} method
71 * will fail if it is called on a "compromised" {@code Properties}
139 class Properties extends Hashtable<Object,Object> {
140 /**
141 * use serialVersionUID from JDK 1.1.X for interoperability
142 */
143 private static final long serialVersionUID = 4112578634029874840L;
144
145 /**
146 * A property list that contains default values for any keys not
147 * found in this property list.
148 *
149 * @serial
150 */
151 protected Properties defaults;
152
153 /**
154 * Properties does not store values in its inherited Hashtable, but instead
155 * in an internal ConcurrentHashMap. Synchronization is omitted from
156 * simple read operations. Writes and bulk operations remain synchronized,
157 * as in Hashtable.
158 */
159 private transient ConcurrentHashMap<Object, Object> map;
160
161 /**
162 * Creates an empty property list with no default values.
163 *
164 * @implNote The initial capacity of a {@code Properties} object created
165 * with this constructor is unspecified.
166 */
167 public Properties() {
168 this(null, 8);
169 }
170
171 /**
172 * Creates an empty property list with no default values, and with an
173 * initial size accommodating the specified number of elements without the
174 * need to dynamically resize.
175 *
176 * @param initialCapacity the {@code Properties} will be sized to
177 * accommodate this many elements
178 * @throws IllegalArgumentException if the initial capacity is less than
179 * zero.
180 */
1456 public synchronized Object compute(Object key,
1457 BiFunction<? super Object, ? super Object, ?> remappingFunction) {
1458 return map.compute(key, remappingFunction);
1459 }
1460
1461 @Override
1462 public synchronized Object merge(Object key, Object value,
1463 BiFunction<? super Object, ? super Object, ?> remappingFunction) {
1464 return map.merge(key, value, remappingFunction);
1465 }
1466
1467 //
1468 // Special Hashtable methods
1469
1470 @Override
1471 protected void rehash() { /* no-op */ }
1472
1473 @Override
1474 public synchronized Object clone() {
1475 Properties clone = (Properties) cloneHashtable();
1476 clone.map = new ConcurrentHashMap<>(map);
1477 return clone;
1478 }
1479
1480 //
1481 // Hashtable serialization overrides
1482 // (these should emit and consume Hashtable-compatible stream)
1483
1484 @Override
1485 void writeHashtable(ObjectOutputStream s) throws IOException {
1486 List<Object> entryStack = new ArrayList<>(map.size() * 2); // an estimate
1487
1488 for (Map.Entry<Object, Object> entry : map.entrySet()) {
1489 entryStack.add(entry.getValue());
1490 entryStack.add(entry.getKey());
1491 }
1492
1493 // Write out the simulated threshold, loadfactor
1494 float loadFactor = 0.75f;
1495 int count = entryStack.size() / 2;
1496 int length = (int)(count / loadFactor) + (count / 20) + 3;
1520 // Read the original length of the array and number of elements
1521 int origlength = s.readInt();
1522 int elements = s.readInt();
1523
1524 // Validate # of elements
1525 if (elements < 0) {
1526 throw new StreamCorruptedException("Illegal # of Elements: " + elements);
1527 }
1528
1529 // Constructing the backing map will lazily create an array when the first element is
1530 // added, so check it before construction. Note that CHM's constructor takes a size
1531 // that is the number of elements to be stored -- not the table size -- so it must be
1532 // inflated by the default load factor of 0.75, then inflated to the next power of two.
1533 // (CHM uses the same power-of-two computation as HashMap, and HashMap.tableSizeFor is
1534 // accessible here.) Check Map.Entry[].class since it's the nearest public type to
1535 // what is actually created.
1536 SharedSecrets.getJavaObjectInputStreamAccess()
1537 .checkArray(s, Map.Entry[].class, HashMap.tableSizeFor((int)(elements / 0.75)));
1538
1539 // create CHM of appropriate capacity
1540 map = new ConcurrentHashMap<>(elements);
1541
1542 // Read all the key/value objects
1543 for (; elements > 0; elements--) {
1544 Object key = s.readObject();
1545 Object value = s.readObject();
1546 map.put(key, value);
1547 }
1548 }
1549 }
|
32 import java.io.OutputStream;
33 import java.io.Reader;
34 import java.io.Writer;
35 import java.io.OutputStreamWriter;
36 import java.io.BufferedWriter;
37 import java.io.ObjectInputStream;
38 import java.io.ObjectOutputStream;
39 import java.io.StreamCorruptedException;
40 import java.io.UnsupportedEncodingException;
41 import java.nio.charset.Charset;
42 import java.nio.charset.IllegalCharsetNameException;
43 import java.nio.charset.UnsupportedCharsetException;
44 import java.util.concurrent.ConcurrentHashMap;
45 import java.util.function.BiConsumer;
46 import java.util.function.BiFunction;
47 import java.util.function.Function;
48
49 import jdk.internal.misc.SharedSecrets;
50 import jdk.internal.util.xml.PropertiesDefaultHandler;
51
52 import jdk.internal.misc.Unsafe;
53
54 /**
55 * The {@code Properties} class represents a persistent set of
56 * properties. The {@code Properties} can be saved to a stream
57 * or loaded from a stream. Each key and its corresponding value in
58 * the property list is a string.
59 * <p>
60 * A property list can contain another property list as its
61 * "defaults"; this second property list is searched if
62 * the property key is not found in the original property list.
63 * <p>
64 * Because {@code Properties} inherits from {@code Hashtable}, the
65 * {@code put} and {@code putAll} methods can be applied to a
66 * {@code Properties} object. Their use is strongly discouraged as they
67 * allow the caller to insert entries whose keys or values are not
68 * {@code Strings}. The {@code setProperty} method should be used
69 * instead. If the {@code store} or {@code save} method is called
70 * on a "compromised" {@code Properties} object that contains a
71 * non-{@code String} key or value, the call will fail. Similarly,
72 * the call to the {@code propertyNames} or {@code list} method
73 * will fail if it is called on a "compromised" {@code Properties}
141 class Properties extends Hashtable<Object,Object> {
142 /**
143 * use serialVersionUID from JDK 1.1.X for interoperability
144 */
145 private static final long serialVersionUID = 4112578634029874840L;
146
147 /**
148 * A property list that contains default values for any keys not
149 * found in this property list.
150 *
151 * @serial
152 */
153 protected Properties defaults;
154
155 /**
156 * Properties does not store values in its inherited Hashtable, but instead
157 * in an internal ConcurrentHashMap. Synchronization is omitted from
158 * simple read operations. Writes and bulk operations remain synchronized,
159 * as in Hashtable.
160 */
161 private transient final ConcurrentHashMap<Object, Object> map;
162
163 private static final Unsafe UNSAFE = Unsafe.getUnsafe();
164 private static final long MAP_OFFSET
165 = UNSAFE.objectFieldOffset(Properties.class, "map");
166 /**
167 * Creates an empty property list with no default values.
168 *
169 * @implNote The initial capacity of a {@code Properties} object created
170 * with this constructor is unspecified.
171 */
172 public Properties() {
173 this(null, 8);
174 }
175
176 /**
177 * Creates an empty property list with no default values, and with an
178 * initial size accommodating the specified number of elements without the
179 * need to dynamically resize.
180 *
181 * @param initialCapacity the {@code Properties} will be sized to
182 * accommodate this many elements
183 * @throws IllegalArgumentException if the initial capacity is less than
184 * zero.
185 */
1461 public synchronized Object compute(Object key,
1462 BiFunction<? super Object, ? super Object, ?> remappingFunction) {
1463 return map.compute(key, remappingFunction);
1464 }
1465
1466 @Override
1467 public synchronized Object merge(Object key, Object value,
1468 BiFunction<? super Object, ? super Object, ?> remappingFunction) {
1469 return map.merge(key, value, remappingFunction);
1470 }
1471
1472 //
1473 // Special Hashtable methods
1474
1475 @Override
1476 protected void rehash() { /* no-op */ }
1477
1478 @Override
1479 public synchronized Object clone() {
1480 Properties clone = (Properties) cloneHashtable();
1481 UNSAFE.putObjectVolatile(clone, MAP_OFFSET, new ConcurrentHashMap<>(map));
1482 return clone;
1483 }
1484
1485 //
1486 // Hashtable serialization overrides
1487 // (these should emit and consume Hashtable-compatible stream)
1488
1489 @Override
1490 void writeHashtable(ObjectOutputStream s) throws IOException {
1491 List<Object> entryStack = new ArrayList<>(map.size() * 2); // an estimate
1492
1493 for (Map.Entry<Object, Object> entry : map.entrySet()) {
1494 entryStack.add(entry.getValue());
1495 entryStack.add(entry.getKey());
1496 }
1497
1498 // Write out the simulated threshold, loadfactor
1499 float loadFactor = 0.75f;
1500 int count = entryStack.size() / 2;
1501 int length = (int)(count / loadFactor) + (count / 20) + 3;
1525 // Read the original length of the array and number of elements
1526 int origlength = s.readInt();
1527 int elements = s.readInt();
1528
1529 // Validate # of elements
1530 if (elements < 0) {
1531 throw new StreamCorruptedException("Illegal # of Elements: " + elements);
1532 }
1533
1534 // Constructing the backing map will lazily create an array when the first element is
1535 // added, so check it before construction. Note that CHM's constructor takes a size
1536 // that is the number of elements to be stored -- not the table size -- so it must be
1537 // inflated by the default load factor of 0.75, then inflated to the next power of two.
1538 // (CHM uses the same power-of-two computation as HashMap, and HashMap.tableSizeFor is
1539 // accessible here.) Check Map.Entry[].class since it's the nearest public type to
1540 // what is actually created.
1541 SharedSecrets.getJavaObjectInputStreamAccess()
1542 .checkArray(s, Map.Entry[].class, HashMap.tableSizeFor((int)(elements / 0.75)));
1543
1544 // create CHM of appropriate capacity
1545 ConcurrentHashMap<Object,Object> tmpMap = new ConcurrentHashMap<>(elements);
1546
1547 // Read all the key/value objects
1548 for (; elements > 0; elements--) {
1549 Object key = s.readObject();
1550 Object value = s.readObject();
1551 tmpMap.put(key, value);
1552 }
1553 UNSAFE.putObjectVolatile(this, MAP_OFFSET, tmpMap);
1554 }
1555 }
|