< prev index next >

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

Print this page

        

*** 32,41 **** --- 32,47 ---- import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.io.OutputStreamWriter; import java.io.BufferedWriter; + import java.io.ObjectInputStream; + import java.io.ObjectOutputStream; + import java.util.concurrent.ConcurrentHashMap; + import java.util.function.BiConsumer; + import java.util.function.BiFunction; + import java.util.function.Function; import jdk.internal.util.xml.PropertiesDefaultHandler; /** * The {@code Properties} class represents a persistent set of
*** 142,151 **** --- 148,160 ---- * Creates an empty property list with the specified defaults. * * @param defaults the defaults. */ public Properties(Properties defaults) { + // use package-private constructor to + // initialize unused fields with dummy values + super((Void) null); this.defaults = defaults; } /** * Calls the <tt>Hashtable</tt> method {@code put}. Provided for
*** 158,168 **** * @return the previous value of the specified key in this property * list, or {@code null} if it did not have one. * @see #getProperty * @since 1.2 */ ! public synchronized Object setProperty(String key, String value) { return put(key, value); } /** --- 167,177 ---- * @return the previous value of the specified key in this property * list, or {@code null} if it did not have one. * @see #getProperty * @since 1.2 */ ! public Object setProperty(String key, String value) { return put(key, value); } /**
*** 310,320 **** * @throws IllegalArgumentException if a malformed Unicode escape * appears in the input. * @throws NullPointerException if {@code reader} is null. * @since 1.6 */ ! public synchronized void load(Reader reader) throws IOException { Objects.requireNonNull(reader, "reader parameter is null"); load0(new LineReader(reader)); } /** --- 319,329 ---- * @throws IllegalArgumentException if a malformed Unicode escape * appears in the input. * @throws NullPointerException if {@code reader} is null. * @since 1.6 */ ! public void load(Reader reader) throws IOException { Objects.requireNonNull(reader, "reader parameter is null"); load0(new LineReader(reader)); } /**
*** 336,346 **** * @throws IllegalArgumentException if the input stream contains a * malformed Unicode escape sequence. * @throws NullPointerException if {@code inStream} is null. * @since 1.2 */ ! public synchronized void load(InputStream inStream) throws IOException { Objects.requireNonNull(inStream, "inStream parameter is null"); load0(new LineReader(inStream)); } private void load0 (LineReader lr) throws IOException { --- 345,355 ---- * @throws IllegalArgumentException if the input stream contains a * malformed Unicode escape sequence. * @throws NullPointerException if {@code inStream} is null. * @since 1.2 */ ! public void load(InputStream inStream) throws IOException { Objects.requireNonNull(inStream, "inStream parameter is null"); load0(new LineReader(inStream)); } private void load0 (LineReader lr) throws IOException {
*** 827,849 **** if (comments != null) { writeComments(bw, comments); } bw.write("#" + new Date().toString()); bw.newLine(); ! synchronized (this) { ! for (Enumeration<?> e = keys(); e.hasMoreElements();) { ! String key = (String)e.nextElement(); ! String val = (String)get(key); key = saveConvert(key, true, escUnicode); /* No need to escape embedded and trailing spaces for value, hence * pass false to flag. */ val = saveConvert(val, false, escUnicode); bw.write(key + "=" + val); bw.newLine(); } - } bw.flush(); } /** * Loads all of the properties represented by the XML document on the --- 836,856 ---- if (comments != null) { writeComments(bw, comments); } bw.write("#" + new Date().toString()); bw.newLine(); ! for (Map.Entry<Object, Object> e : entrySet()) { ! String key = (String)e.getKey(); ! String val = (String)e.getValue(); key = saveConvert(key, true, escUnicode); /* No need to escape embedded and trailing spaces for value, hence * pass false to flag. */ val = saveConvert(val, false, escUnicode); bw.write(key + "=" + val); bw.newLine(); } bw.flush(); } /** * Loads all of the properties represented by the XML document on the
*** 874,884 **** * @see #storeToXML(OutputStream, String, String) * @see <a href="http://www.w3.org/TR/REC-xml/#charencoding">Character * Encoding in Entities</a> * @since 1.5 */ ! public synchronized void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException { Objects.requireNonNull(in); PropertiesDefaultHandler handler = new PropertiesDefaultHandler(); handler.load(this, in); --- 881,891 ---- * @see #storeToXML(OutputStream, String, String) * @see <a href="http://www.w3.org/TR/REC-xml/#charencoding">Character * Encoding in Entities</a> * @since 1.5 */ ! public void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException { Objects.requireNonNull(in); PropertiesDefaultHandler handler = new PropertiesDefaultHandler(); handler.load(this, in);
*** 969,979 **** * @return the value in this property list with the specified key value. * @see #setProperty * @see #defaults */ public String getProperty(String key) { ! Object oval = super.get(key); String sval = (oval instanceof String) ? (String)oval : null; return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval; } /** --- 976,986 ---- * @return the value in this property list with the specified key value. * @see #setProperty * @see #defaults */ public String getProperty(String key) { ! Object oval = map.get(key); String sval = (oval instanceof String) ? (String)oval : null; return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval; } /**
*** 1007,1017 **** * @see java.util.Enumeration * @see java.util.Properties#defaults * @see #stringPropertyNames */ public Enumeration<?> propertyNames() { ! Hashtable<String,Object> h = new Hashtable<>(); enumerate(h); return h.keys(); } /** --- 1014,1024 ---- * @see java.util.Enumeration * @see java.util.Properties#defaults * @see #stringPropertyNames */ public Enumeration<?> propertyNames() { ! Hashtable<String, Object> h = new Hashtable<>(); enumerate(h); return h.keys(); } /**
*** 1031,1041 **** * including the keys in the default property list. * @see java.util.Properties#defaults * @since 1.6 */ public Set<String> stringPropertyNames() { ! Hashtable<String, String> h = new Hashtable<>(); enumerateStringProperties(h); return h.keySet(); } /** --- 1038,1048 ---- * including the keys in the default property list. * @see java.util.Properties#defaults * @since 1.6 */ public Set<String> stringPropertyNames() { ! Map<String, String> h = new HashMap<>(); enumerateStringProperties(h); return h.keySet(); } /**
*** 1046,1060 **** * @throws ClassCastException if any key in this property list * is not a string. */ public void list(PrintStream out) { out.println("-- listing properties --"); ! Hashtable<String,Object> h = new Hashtable<>(); enumerate(h); ! for (Enumeration<String> e = h.keys() ; e.hasMoreElements() ;) { ! String key = e.nextElement(); ! String val = (String)h.get(key); if (val.length() > 40) { val = val.substring(0, 37) + "..."; } out.println(key + "=" + val); } --- 1053,1067 ---- * @throws ClassCastException if any key in this property list * is not a string. */ public void list(PrintStream out) { out.println("-- listing properties --"); ! Map<String, Object> h = new HashMap<>(); enumerate(h); ! for (Map.Entry<String, Object> e : h.entrySet()) { ! String key = e.getKey(); ! String val = (String)e.getValue(); if (val.length() > 40) { val = val.substring(0, 37) + "..."; } out.println(key + "=" + val); }
*** 1074,1123 **** * method is duplicated in order to ensure that a non-1.1 compiler can * compile this file. */ public void list(PrintWriter out) { out.println("-- listing properties --"); ! Hashtable<String,Object> h = new Hashtable<>(); enumerate(h); ! for (Enumeration<String> e = h.keys() ; e.hasMoreElements() ;) { ! String key = e.nextElement(); ! String val = (String)h.get(key); if (val.length() > 40) { val = val.substring(0, 37) + "..."; } out.println(key + "=" + val); } } /** ! * Enumerates all key/value pairs in the specified hashtable. ! * @param h the hashtable * @throws ClassCastException if any of the property keys * is not of String type. */ ! private synchronized void enumerate(Hashtable<String,Object> h) { if (defaults != null) { defaults.enumerate(h); } ! for (Enumeration<?> e = keys() ; e.hasMoreElements() ;) { ! String key = (String)e.nextElement(); ! h.put(key, get(key)); } } /** ! * Enumerates all key/value pairs in the specified hashtable * and omits the property if the key or value is not a string. ! * @param h the hashtable */ ! private synchronized void enumerateStringProperties(Hashtable<String, String> h) { if (defaults != null) { defaults.enumerateStringProperties(h); } ! for (Enumeration<?> e = keys() ; e.hasMoreElements() ;) { ! Object k = e.nextElement(); ! Object v = get(k); if (k instanceof String && v instanceof String) { h.put((String) k, (String) v); } } } --- 1081,1130 ---- * method is duplicated in order to ensure that a non-1.1 compiler can * compile this file. */ public void list(PrintWriter out) { out.println("-- listing properties --"); ! Map<String, Object> h = new HashMap<>(); enumerate(h); ! for (Map.Entry<String, Object> e : h.entrySet()) { ! String key = e.getKey(); ! String val = (String)e.getValue(); if (val.length() > 40) { val = val.substring(0, 37) + "..."; } out.println(key + "=" + val); } } /** ! * Enumerates all key/value pairs in the specified Map. ! * @param h the Map * @throws ClassCastException if any of the property keys * is not of String type. */ ! private void enumerate(Map<String, Object> h) { if (defaults != null) { defaults.enumerate(h); } ! for (Map.Entry<Object, Object> e : entrySet()) { ! String key = (String)e.getKey(); ! h.put(key, e.getValue()); } } /** ! * Enumerates all key/value pairs in the specified Map * and omits the property if the key or value is not a string. ! * @param h the Map */ ! private void enumerateStringProperties(Map<String, String> h) { if (defaults != null) { defaults.enumerateStringProperties(h); } ! for (Map.Entry<Object, Object> e : entrySet()) { ! Object k = e.getKey(); ! Object v = e.getValue(); if (k instanceof String && v instanceof String) { h.put((String) k, (String) v); } } }
*** 1132,1137 **** --- 1139,1369 ---- /** A table of hex digits */ private static final char[] hexDigit = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; + + // + // Hashtable methods overridden and delegated to a ConcurrentHashMap instance + + private transient ConcurrentHashMap<Object, Object> map = + new ConcurrentHashMap<>(8); + + @Override + public int size() { + return map.size(); + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + public Enumeration<Object> keys() { + return map.keys(); + } + + @Override + public Enumeration<Object> elements() { + return map.elements(); + } + + @Override + public boolean contains(Object value) { + return map.contains(value); + } + + @Override + public boolean containsValue(Object value) { + return map.containsValue(value); + } + + @Override + public boolean containsKey(Object key) { + return map.containsKey(key); + } + + @Override + public Object get(Object key) { + return map.get(key); + } + + @Override + public Object put(Object key, Object value) { + return map.put(key, value); + } + + @Override + public Object remove(Object key) { + return map.remove(key); + } + + @Override + public void putAll(Map<?, ?> t) { + map.putAll(t); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public String toString() { + return map.toString(); + } + + @Override + public Set<Object> keySet() { + return map.keySet(); + } + + @Override + public Set<Map.Entry<Object, Object>> entrySet() { + return map.entrySet(); + } + + @Override + public Collection<Object> values() { + return map.values(); + } + + @Override + public boolean equals(Object o) { + return map.equals(o); + } + + @Override + public int hashCode() { + return map.hashCode(); + } + + @Override + public Object getOrDefault(Object key, Object defaultValue) { + return map.getOrDefault(key, defaultValue); + } + + @Override + public void forEach(BiConsumer<? super Object, ? super Object> action) { + map.forEach(action); + } + + @Override + public void replaceAll(BiFunction<? super Object, ? super Object, ?> function) { + map.replaceAll(function); + } + + @Override + public Object putIfAbsent(Object key, Object value) { + return map.putIfAbsent(key, value); + } + + @Override + public boolean remove(Object key, Object value) { + return map.remove(key, value); + } + + @Override + public boolean replace(Object key, Object oldValue, Object newValue) { + return map.replace(key, oldValue, newValue); + } + + @Override + public Object replace(Object key, Object value) { + return map.replace(key, value); + } + + @Override + public Object computeIfAbsent(Object key, + Function<? super Object, ?> mappingFunction) { + return map.computeIfAbsent(key, mappingFunction); + } + + @Override + public Object computeIfPresent(Object key, + BiFunction<? super Object, ? super Object, ?> remappingFunction) { + return map.computeIfPresent(key, remappingFunction); + } + + @Override + public Object compute(Object key, + BiFunction<? super Object, ? super Object, ?> remappingFunction) { + return map.compute(key, remappingFunction); + } + + @Override + public Object merge(Object key, Object value, + BiFunction<? super Object, ? super Object, ?> remappingFunction) { + return map.merge(key, value, remappingFunction); + } + + // + // Special Hashtable methods + + @Override + protected void rehash() { + // no-op + } + + @Override + public Object clone() { + Properties clone = (Properties) cloneHashtable(); + clone.map = new ConcurrentHashMap<>(map); + return clone; + } + + // + // Hashtable serialization overrides + // (these should emit and consume Hashtable-compatible stream) + + @Override + void writeHashtable(ObjectOutputStream s) throws IOException { + List<Object> entryStack = new ArrayList<>(map.size() * 2); // an estimate + + for (Map.Entry<Object, Object> entry : map.entrySet()) { + entryStack.add(entry.getValue()); + entryStack.add(entry.getKey()); + } + + // Write out the simulated threshold, loadfactor + float loadFactor = 0.75f; + int count = entryStack.size() / 2; + int length = (int)(count / loadFactor) + (count / 20) + 3; + if (length > count && (length & 1) == 0) { + length--; + } + synchronized (map) { // in case of multiple concurrent serializations + defaultWriteHashtable(s, length, loadFactor); + } + + // Write out simulated length and real count of elements + s.writeInt(length); + s.writeInt(count); + + // Write out the key/value objects from the stacked entries + for (int i = entryStack.size() - 1; i >= 0; i--) { + s.writeObject(entryStack.get(i)); + } + } + + @Override + void readHashtable(ObjectInputStream s) throws IOException, + ClassNotFoundException { + // Read in the threshold and loadfactor + s.defaultReadObject(); + + // Read the original length of the array and number of elements + int origlength = s.readInt(); + int elements = s.readInt(); + + // create CHM of appropriate capacity + map = new ConcurrentHashMap<>(elements); + + // Read all the key/value objects + for (; elements > 0; elements--) { + Object key = s.readObject(); + Object value = s.readObject(); + map.put(key, value); + } + } }
< prev index next >