< prev index next >

src/java.base/share/classes/java/util/Properties.java

Print this page




  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 }
< prev index next >