20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.util;
27
28 import java.io.IOException;
29 import java.io.PrintStream;
30 import java.io.PrintWriter;
31 import java.io.InputStream;
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.security.AccessController;
38 import java.security.PrivilegedAction;
39
40 import sun.util.spi.XmlPropertiesProvider;
41
42 /**
43 * The {@code Properties} class represents a persistent set of
44 * properties. The {@code Properties} can be saved to a stream
45 * or loaded from a stream. Each key and its corresponding value in
46 * the property list is a string.
47 * <p>
48 * A property list can contain another property list as its
49 * "defaults"; this second property list is searched if
50 * the property key is not found in the original property list.
51 * <p>
52 * Because {@code Properties} inherits from {@code Hashtable}, the
53 * {@code put} and {@code putAll} methods can be applied to a
54 * {@code Properties} object. Their use is strongly discouraged as they
55 * allow the caller to insert entries whose keys or values are not
56 * {@code Strings}. The {@code setProperty} method should be used
57 * instead. If the {@code store} or {@code save} method is called
58 * on a "compromised" {@code Properties} object that contains a
59 * non-{@code String} key or value, the call will fail. Similarly,
60 * the call to the {@code propertyNames} or {@code list} method
860 *
861 * <p>The specified stream is closed after this method returns.
862 *
863 * @param in the input stream from which to read the XML document.
864 * @throws IOException if reading from the specified input stream
865 * results in an <tt>IOException</tt>.
866 * @throws java.io.UnsupportedEncodingException if the document's encoding
867 * declaration can be read and it specifies an encoding that is not
868 * supported
869 * @throws InvalidPropertiesFormatException Data on input stream does not
870 * constitute a valid XML document with the mandated document type.
871 * @throws NullPointerException if {@code in} is null.
872 * @see #storeToXML(OutputStream, String, String)
873 * @see <a href="http://www.w3.org/TR/REC-xml/#charencoding">Character
874 * Encoding in Entities</a>
875 * @since 1.5
876 */
877 public synchronized void loadFromXML(InputStream in)
878 throws IOException, InvalidPropertiesFormatException
879 {
880 XmlSupport.load(this, Objects.requireNonNull(in));
881 in.close();
882 }
883
884 /**
885 * Emits an XML document representing all of the properties contained
886 * in this table.
887 *
888 * <p> An invocation of this method of the form <tt>props.storeToXML(os,
889 * comment)</tt> behaves in exactly the same way as the invocation
890 * <tt>props.storeToXML(os, comment, "UTF-8");</tt>.
891 *
892 * @param os the output stream on which to emit the XML document.
893 * @param comment a description of the property list, or {@code null}
894 * if no comment is desired.
895 * @throws IOException if writing to the specified output stream
896 * results in an <tt>IOException</tt>.
897 * @throws NullPointerException if {@code os} is null.
898 * @throws ClassCastException if this {@code Properties} object
899 * contains any keys or values that are not
900 * {@code Strings}.
932 * <a href="../lang/package-summary.html#charenc">
933 * character encoding</a>
934 *
935 * @throws IOException if writing to the specified output stream
936 * results in an <tt>IOException</tt>.
937 * @throws java.io.UnsupportedEncodingException if the encoding is not
938 * supported by the implementation.
939 * @throws NullPointerException if {@code os} is {@code null},
940 * or if {@code encoding} is {@code null}.
941 * @throws ClassCastException if this {@code Properties} object
942 * contains any keys or values that are not
943 * {@code Strings}.
944 * @see #loadFromXML(InputStream)
945 * @see <a href="http://www.w3.org/TR/REC-xml/#charencoding">Character
946 * Encoding in Entities</a>
947 * @since 1.5
948 */
949 public void storeToXML(OutputStream os, String comment, String encoding)
950 throws IOException
951 {
952 XmlSupport.save(this, Objects.requireNonNull(os), comment,
953 Objects.requireNonNull(encoding));
954 }
955
956 /**
957 * Searches for the property with the specified key in this property list.
958 * If the key is not found in this property list, the default property list,
959 * and its defaults, recursively, are then checked. The method returns
960 * {@code null} if the property is not found.
961 *
962 * @param key the property key.
963 * @return the value in this property list with the specified key value.
964 * @see #setProperty
965 * @see #defaults
966 */
967 public String getProperty(String key) {
968 Object oval = super.get(key);
969 String sval = (oval instanceof String) ? (String)oval : null;
970 return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
971 }
972
973 /**
1111 Object k = e.nextElement();
1112 Object v = get(k);
1113 if (k instanceof String && v instanceof String) {
1114 h.put((String) k, (String) v);
1115 }
1116 }
1117 }
1118
1119 /**
1120 * Convert a nibble to a hex character
1121 * @param nibble the nibble to convert.
1122 */
1123 private static char toHex(int nibble) {
1124 return hexDigit[(nibble & 0xF)];
1125 }
1126
1127 /** A table of hex digits */
1128 private static final char[] hexDigit = {
1129 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
1130 };
1131
1132 /**
1133 * Supporting class for loading/storing properties in XML format.
1134 *
1135 * <p> The {@code load} and {@code store} methods defined here delegate to a
1136 * system-wide {@code XmlPropertiesProvider}. On first invocation of either
1137 * method then the system-wide provider is located as follows: </p>
1138 *
1139 * <ol>
1140 * <li> If the system property {@code sun.util.spi.XmlPropertiesProvider}
1141 * is defined then it is taken to be the full-qualified name of a concrete
1142 * provider class. The class is loaded with the system class loader as the
1143 * initiating loader. If it cannot be loaded or instantiated using a zero
1144 * argument constructor then an unspecified error is thrown. </li>
1145 *
1146 * <li> If the system property is not defined then the service-provider
1147 * loading facility defined by the {@link ServiceLoader} class is used to
1148 * locate a provider with the system class loader as the initiating
1149 * loader and {@code sun.util.spi.XmlPropertiesProvider} as the service
1150 * type. If this process fails then an unspecified error is thrown. If
1151 * there is more than one service provider installed then it is
1152 * not specified as to which provider will be used. </li>
1153 *
1154 * <li> If the provider is not found by the above means then a system
1155 * default provider will be instantiated and used. </li>
1156 * </ol>
1157 */
1158 private static class XmlSupport {
1159
1160 private static XmlPropertiesProvider loadProviderFromProperty(ClassLoader cl) {
1161 String cn = System.getProperty("sun.util.spi.XmlPropertiesProvider");
1162 if (cn == null)
1163 return null;
1164 try {
1165 Class<?> c = Class.forName(cn, true, cl);
1166 return (XmlPropertiesProvider)c.newInstance();
1167 } catch (ClassNotFoundException |
1168 IllegalAccessException |
1169 InstantiationException x) {
1170 throw new ServiceConfigurationError(null, x);
1171 }
1172 }
1173
1174 private static XmlPropertiesProvider loadProviderAsService(ClassLoader cl) {
1175 Iterator<XmlPropertiesProvider> iterator =
1176 ServiceLoader.load(XmlPropertiesProvider.class, cl).iterator();
1177 return iterator.hasNext() ? iterator.next() : null;
1178 }
1179
1180 private static XmlPropertiesProvider loadProvider() {
1181 return AccessController.doPrivileged(
1182 new PrivilegedAction<XmlPropertiesProvider>() {
1183 public XmlPropertiesProvider run() {
1184 ClassLoader cl = ClassLoader.getSystemClassLoader();
1185 XmlPropertiesProvider provider = loadProviderFromProperty(cl);
1186 if (provider != null)
1187 return provider;
1188 provider = loadProviderAsService(cl);
1189 if (provider != null)
1190 return provider;
1191 return new jdk.internal.util.xml.BasicXmlPropertiesProvider();
1192 }});
1193 }
1194
1195 private static final XmlPropertiesProvider PROVIDER = loadProvider();
1196
1197 static void load(Properties props, InputStream in)
1198 throws IOException, InvalidPropertiesFormatException
1199 {
1200 PROVIDER.load(props, in);
1201 }
1202
1203 static void save(Properties props, OutputStream os, String comment,
1204 String encoding)
1205 throws IOException
1206 {
1207 PROVIDER.store(props, os, comment, encoding);
1208 }
1209 }
1210 }
|
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.util;
27
28 import java.io.IOException;
29 import java.io.PrintStream;
30 import java.io.PrintWriter;
31 import java.io.InputStream;
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.security.AccessController;
38 import java.security.PrivilegedAction;
39
40 import jdk.internal.util.xml.PropertiesDefaultHandler;
41
42 /**
43 * The {@code Properties} class represents a persistent set of
44 * properties. The {@code Properties} can be saved to a stream
45 * or loaded from a stream. Each key and its corresponding value in
46 * the property list is a string.
47 * <p>
48 * A property list can contain another property list as its
49 * "defaults"; this second property list is searched if
50 * the property key is not found in the original property list.
51 * <p>
52 * Because {@code Properties} inherits from {@code Hashtable}, the
53 * {@code put} and {@code putAll} methods can be applied to a
54 * {@code Properties} object. Their use is strongly discouraged as they
55 * allow the caller to insert entries whose keys or values are not
56 * {@code Strings}. The {@code setProperty} method should be used
57 * instead. If the {@code store} or {@code save} method is called
58 * on a "compromised" {@code Properties} object that contains a
59 * non-{@code String} key or value, the call will fail. Similarly,
60 * the call to the {@code propertyNames} or {@code list} method
860 *
861 * <p>The specified stream is closed after this method returns.
862 *
863 * @param in the input stream from which to read the XML document.
864 * @throws IOException if reading from the specified input stream
865 * results in an <tt>IOException</tt>.
866 * @throws java.io.UnsupportedEncodingException if the document's encoding
867 * declaration can be read and it specifies an encoding that is not
868 * supported
869 * @throws InvalidPropertiesFormatException Data on input stream does not
870 * constitute a valid XML document with the mandated document type.
871 * @throws NullPointerException if {@code in} is null.
872 * @see #storeToXML(OutputStream, String, String)
873 * @see <a href="http://www.w3.org/TR/REC-xml/#charencoding">Character
874 * Encoding in Entities</a>
875 * @since 1.5
876 */
877 public synchronized void loadFromXML(InputStream in)
878 throws IOException, InvalidPropertiesFormatException
879 {
880 Objects.requireNonNull(in);
881 PropertiesDefaultHandler handler = new PropertiesDefaultHandler();
882 handler.load(this, in);
883 in.close();
884 }
885
886 /**
887 * Emits an XML document representing all of the properties contained
888 * in this table.
889 *
890 * <p> An invocation of this method of the form <tt>props.storeToXML(os,
891 * comment)</tt> behaves in exactly the same way as the invocation
892 * <tt>props.storeToXML(os, comment, "UTF-8");</tt>.
893 *
894 * @param os the output stream on which to emit the XML document.
895 * @param comment a description of the property list, or {@code null}
896 * if no comment is desired.
897 * @throws IOException if writing to the specified output stream
898 * results in an <tt>IOException</tt>.
899 * @throws NullPointerException if {@code os} is null.
900 * @throws ClassCastException if this {@code Properties} object
901 * contains any keys or values that are not
902 * {@code Strings}.
934 * <a href="../lang/package-summary.html#charenc">
935 * character encoding</a>
936 *
937 * @throws IOException if writing to the specified output stream
938 * results in an <tt>IOException</tt>.
939 * @throws java.io.UnsupportedEncodingException if the encoding is not
940 * supported by the implementation.
941 * @throws NullPointerException if {@code os} is {@code null},
942 * or if {@code encoding} is {@code null}.
943 * @throws ClassCastException if this {@code Properties} object
944 * contains any keys or values that are not
945 * {@code Strings}.
946 * @see #loadFromXML(InputStream)
947 * @see <a href="http://www.w3.org/TR/REC-xml/#charencoding">Character
948 * Encoding in Entities</a>
949 * @since 1.5
950 */
951 public void storeToXML(OutputStream os, String comment, String encoding)
952 throws IOException
953 {
954 Objects.requireNonNull(os);
955 Objects.requireNonNull(encoding);
956 PropertiesDefaultHandler handler = new PropertiesDefaultHandler();
957 handler.store(this, os, comment, encoding);
958 }
959
960 /**
961 * Searches for the property with the specified key in this property list.
962 * If the key is not found in this property list, the default property list,
963 * and its defaults, recursively, are then checked. The method returns
964 * {@code null} if the property is not found.
965 *
966 * @param key the property key.
967 * @return the value in this property list with the specified key value.
968 * @see #setProperty
969 * @see #defaults
970 */
971 public String getProperty(String key) {
972 Object oval = super.get(key);
973 String sval = (oval instanceof String) ? (String)oval : null;
974 return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
975 }
976
977 /**
1115 Object k = e.nextElement();
1116 Object v = get(k);
1117 if (k instanceof String && v instanceof String) {
1118 h.put((String) k, (String) v);
1119 }
1120 }
1121 }
1122
1123 /**
1124 * Convert a nibble to a hex character
1125 * @param nibble the nibble to convert.
1126 */
1127 private static char toHex(int nibble) {
1128 return hexDigit[(nibble & 0xF)];
1129 }
1130
1131 /** A table of hex digits */
1132 private static final char[] hexDigit = {
1133 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
1134 };
1135 }
|