Creates an {@code ImmutableMap<String, String>} from a {@code Properties} instance. Properties normally derive from {@code Map<Object, Object>}, but they typically contain strings, which is awkward. This method lets you get a plain-old-{@code Map} out of a {@code Properties}. @param properties a {@
(Properties properties)
| 1399 | * @throws NullPointerException if any key or value in {@code properties} is null |
| 1400 | */ |
| 1401 | @J2ktIncompatible |
| 1402 | @GwtIncompatible // java.util.Properties |
| 1403 | public static ImmutableMap<String, String> fromProperties(Properties properties) { |
| 1404 | ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); |
| 1405 | |
| 1406 | for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements(); ) { |
| 1407 | /* |
| 1408 | * requireNonNull is safe because propertyNames contains only non-null elements. |
| 1409 | * |
| 1410 | * Accordingly, we have it annotated as returning `Enumeration<? extends Object>` in our |
| 1411 | * prototype checker's JDK. However, the checker still sees the return type as plain |
| 1412 | * `Enumeration<?>`, probably because of one of the following two bugs (and maybe those two |
| 1413 | * bugs are themselves just symptoms of the same underlying problem): |
| 1414 | * |
| 1415 | * https://github.com/typetools/checker-framework/issues/3030 |
| 1416 | * |
| 1417 | * https://github.com/typetools/checker-framework/issues/3236 |
| 1418 | */ |
| 1419 | String key = (String) requireNonNull(e.nextElement()); |
| 1420 | /* |
| 1421 | * requireNonNull is safe because the key came from propertyNames... |
| 1422 | * |
| 1423 | * ...except that it's possible for users to insert a string key with a non-string value, and |
| 1424 | * in that case, getProperty *will* return null. |
| 1425 | * |
| 1426 | * TODO(b/192002623): Handle that case: Either: |
| 1427 | * |
| 1428 | * - Skip non-string keys and values entirely, as proposed in the linked bug. |
| 1429 | * |
| 1430 | * - Throw ClassCastException instead of NullPointerException, as documented in the current |
| 1431 | * Javadoc. (Note that we can't necessarily "just" change our call to `getProperty` to `get` |
| 1432 | * because `get` does not consult the default properties.) |
| 1433 | */ |
| 1434 | builder.put(key, requireNonNull(properties.getProperty(key))); |
| 1435 | } |
| 1436 | |
| 1437 | return builder.buildOrThrow(); |
| 1438 | } |
| 1439 | |
| 1440 | /** |
| 1441 | * Returns an immutable map entry with the specified key and value. The {@link Entry#setValue} |