jdk/src/share/classes/java/security/Provider.java
changeset 21340 17142dadfffe
parent 18592 80cdfecea074
child 21979 3dcd1bc15edd
equal deleted inserted replaced
21330:7b073d91ba9e 21340:17142dadfffe
    28 import java.io.*;
    28 import java.io.*;
    29 import java.util.*;
    29 import java.util.*;
    30 import static java.util.Locale.ENGLISH;
    30 import static java.util.Locale.ENGLISH;
    31 import java.lang.ref.*;
    31 import java.lang.ref.*;
    32 import java.lang.reflect.*;
    32 import java.lang.reflect.*;
       
    33 import java.util.function.BiConsumer;
       
    34 import java.util.function.BiFunction;
       
    35 import java.util.function.Function;
    33 
    36 
    34 /**
    37 /**
    35  * This class represents a "provider" for the
    38  * This class represents a "provider" for the
    36  * Java Security API, where a provider implements some or all parts of
    39  * Java Security API, where a provider implements some or all parts of
    37  * Java Security. Services that a provider may implement include:
    40  * Java Security. Services that a provider may implement include:
   183 
   186 
   184     /**
   187     /**
   185      * Clears this provider so that it no longer contains the properties
   188      * Clears this provider so that it no longer contains the properties
   186      * used to look up facilities implemented by the provider.
   189      * used to look up facilities implemented by the provider.
   187      *
   190      *
   188      * <p>First, if there is a security manager, its
   191      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
   189      * {@code checkSecurityAccess} method is called with the string
   192      * method is called with the string {@code "clearProviderProperties."+name}
   190      * {@code "clearProviderProperties."+name} (where {@code name}
   193      * (where {@code name} is the provider name) to see if it's ok to clear
   191      * is the provider name) to see if it's ok to clear this provider.
   194      * this provider.
   192      * If the default implementation of {@code checkSecurityAccess}
       
   193      * is used (that is, that method is not overriden), then this results in
       
   194      * a call to the security manager's {@code checkPermission} method
       
   195      * with a {@code SecurityPermission("clearProviderProperties."+name)}
       
   196      * permission.
       
   197      *
   195      *
   198      * @throws  SecurityException
   196      * @throws  SecurityException
   199      *          if a security manager exists and its {@link
   197      *          if a security manager exists and its {@link
   200      *          java.lang.SecurityManager#checkSecurityAccess} method
   198      *          java.lang.SecurityManager#checkSecurityAccess} method
   201      *          denies access to clear this provider
   199      *          denies access to clear this provider
   202      *
   200      *
   203      * @since 1.2
   201      * @since 1.2
   204      */
   202      */
       
   203     @Override
   205     public synchronized void clear() {
   204     public synchronized void clear() {
   206         check("clearProviderProperties."+name);
   205         check("clearProviderProperties."+name);
   207         if (debug != null) {
   206         if (debug != null) {
   208             debug.println("Remove " + name + " provider properties");
   207             debug.println("Remove " + name + " provider properties");
   209         }
   208         }
   216      * @param inStream   the input stream.
   215      * @param inStream   the input stream.
   217      * @exception  IOException  if an error occurred when reading from the
   216      * @exception  IOException  if an error occurred when reading from the
   218      *               input stream.
   217      *               input stream.
   219      * @see java.util.Properties#load
   218      * @see java.util.Properties#load
   220      */
   219      */
       
   220     @Override
   221     public synchronized void load(InputStream inStream) throws IOException {
   221     public synchronized void load(InputStream inStream) throws IOException {
   222         check("putProviderProperty."+name);
   222         check("putProviderProperty."+name);
   223         if (debug != null) {
   223         if (debug != null) {
   224             debug.println("Load " + name + " provider properties");
   224             debug.println("Load " + name + " provider properties");
   225         }
   225         }
   233      * These mappings will replace any properties that this provider had
   233      * These mappings will replace any properties that this provider had
   234      * for any of the keys currently in the specified Map.
   234      * for any of the keys currently in the specified Map.
   235      *
   235      *
   236      * @since 1.2
   236      * @since 1.2
   237      */
   237      */
       
   238     @Override
   238     public synchronized void putAll(Map<?,?> t) {
   239     public synchronized void putAll(Map<?,?> t) {
   239         check("putProviderProperty."+name);
   240         check("putProviderProperty."+name);
   240         if (debug != null) {
   241         if (debug != null) {
   241             debug.println("Put all " + name + " provider properties");
   242             debug.println("Put all " + name + " provider properties");
   242         }
   243         }
   248      * in this Provider.
   249      * in this Provider.
   249      *
   250      *
   250      * @see   java.util.Map.Entry
   251      * @see   java.util.Map.Entry
   251      * @since 1.2
   252      * @since 1.2
   252      */
   253      */
       
   254     @Override
   253     public synchronized Set<Map.Entry<Object,Object>> entrySet() {
   255     public synchronized Set<Map.Entry<Object,Object>> entrySet() {
   254         checkInitialized();
   256         checkInitialized();
   255         if (entrySet == null) {
   257         if (entrySet == null) {
   256             if (entrySetCallCount++ == 0)  // Initial call
   258             if (entrySetCallCount++ == 0)  // Initial call
   257                 entrySet = Collections.unmodifiableMap(this).entrySet();
   259                 entrySet = Collections.unmodifiableMap(this).entrySet();
   274      * Returns an unmodifiable Set view of the property keys contained in
   276      * Returns an unmodifiable Set view of the property keys contained in
   275      * this provider.
   277      * this provider.
   276      *
   278      *
   277      * @since 1.2
   279      * @since 1.2
   278      */
   280      */
       
   281     @Override
   279     public Set<Object> keySet() {
   282     public Set<Object> keySet() {
   280         checkInitialized();
   283         checkInitialized();
   281         return Collections.unmodifiableSet(super.keySet());
   284         return Collections.unmodifiableSet(super.keySet());
   282     }
   285     }
   283 
   286 
   285      * Returns an unmodifiable Collection view of the property values
   288      * Returns an unmodifiable Collection view of the property values
   286      * contained in this provider.
   289      * contained in this provider.
   287      *
   290      *
   288      * @since 1.2
   291      * @since 1.2
   289      */
   292      */
       
   293     @Override
   290     public Collection<Object> values() {
   294     public Collection<Object> values() {
   291         checkInitialized();
   295         checkInitialized();
   292         return Collections.unmodifiableCollection(super.values());
   296         return Collections.unmodifiableCollection(super.values());
   293     }
   297     }
   294 
   298 
   295     /**
   299     /**
   296      * Sets the {@code key} property to have the specified
   300      * Sets the {@code key} property to have the specified
   297      * {@code value}.
   301      * {@code value}.
   298      *
   302      *
   299      * <p>First, if there is a security manager, its
   303      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
   300      * {@code checkSecurityAccess} method is called with the string
   304      * method is called with the string {@code "putProviderProperty."+name},
   301      * {@code "putProviderProperty."+name}, where {@code name} is the
   305      * where {@code name} is the provider name, to see if it's ok to set this
   302      * provider name, to see if it's ok to set this provider's property values.
   306      * provider's property values.
   303      * If the default implementation of {@code checkSecurityAccess}
       
   304      * is used (that is, that method is not overriden), then this results in
       
   305      * a call to the security manager's {@code checkPermission} method
       
   306      * with a {@code SecurityPermission("putProviderProperty."+name)}
       
   307      * permission.
       
   308      *
       
   309      * @param key the property key.
       
   310      *
       
   311      * @param value the property value.
       
   312      *
       
   313      * @return the previous value of the specified property
       
   314      * ({@code key}), or null if it did not have one.
       
   315      *
   307      *
   316      * @throws  SecurityException
   308      * @throws  SecurityException
   317      *          if a security manager exists and its {@link
   309      *          if a security manager exists and its {@link
   318      *          java.lang.SecurityManager#checkSecurityAccess} method
   310      *          java.lang.SecurityManager#checkSecurityAccess} method
   319      *          denies access to set property values.
   311      *          denies access to set property values.
   320      *
   312      *
   321      * @since 1.2
   313      * @since 1.2
   322      */
   314      */
       
   315     @Override
   323     public synchronized Object put(Object key, Object value) {
   316     public synchronized Object put(Object key, Object value) {
   324         check("putProviderProperty."+name);
   317         check("putProviderProperty."+name);
   325         if (debug != null) {
   318         if (debug != null) {
   326             debug.println("Set " + name + " provider property [" +
   319             debug.println("Set " + name + " provider property [" +
   327                           key + "/" + value +"]");
   320                           key + "/" + value +"]");
   328         }
   321         }
   329         return implPut(key, value);
   322         return implPut(key, value);
   330     }
   323     }
   331 
   324 
   332     /**
   325     /**
       
   326      * If the specified key is not already associated with a value (or is mapped
       
   327      * to {@code null}) associates it with the given value and returns
       
   328      * {@code null}, else returns the current value.
       
   329      *
       
   330      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
       
   331      * method is called with the string {@code "putProviderProperty."+name},
       
   332      * where {@code name} is the provider name, to see if it's ok to set this
       
   333      * provider's property values.
       
   334      *
       
   335      * @throws  SecurityException
       
   336      *          if a security manager exists and its {@link
       
   337      *          java.lang.SecurityManager#checkSecurityAccess} method
       
   338      *          denies access to set property values.
       
   339      */
       
   340     @Override
       
   341     public synchronized Object putIfAbsent(Object key, Object value) {
       
   342         check("putProviderProperty."+name);
       
   343         if (debug != null) {
       
   344             debug.println("Set " + name + " provider property [" +
       
   345                           key + "/" + value +"]");
       
   346         }
       
   347         return implPutIfAbsent(key, value);
       
   348     }
       
   349 
       
   350     /**
   333      * Removes the {@code key} property (and its corresponding
   351      * Removes the {@code key} property (and its corresponding
   334      * {@code value}).
   352      * {@code value}).
   335      *
   353      *
   336      * <p>First, if there is a security manager, its
   354      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
   337      * {@code checkSecurityAccess} method is called with the string
   355      * method is called with the string {@code "removeProviderProperty."+name},
   338      * {@code "removeProviderProperty."+name}, where {@code name} is
   356      * where {@code name} is the provider name, to see if it's ok to remove this
   339      * the provider name, to see if it's ok to remove this provider's
   357      * provider's properties.
   340      * properties. If the default implementation of
       
   341      * {@code checkSecurityAccess} is used (that is, that method is not
       
   342      * overriden), then this results in a call to the security manager's
       
   343      * {@code checkPermission} method with a
       
   344      * {@code SecurityPermission("removeProviderProperty."+name)}
       
   345      * permission.
       
   346      *
       
   347      * @param key the key for the property to be removed.
       
   348      *
       
   349      * @return the value to which the key had been mapped,
       
   350      * or null if the key did not have a mapping.
       
   351      *
   358      *
   352      * @throws  SecurityException
   359      * @throws  SecurityException
   353      *          if a security manager exists and its {@link
   360      *          if a security manager exists and its {@link
   354      *          java.lang.SecurityManager#checkSecurityAccess} method
   361      *          java.lang.SecurityManager#checkSecurityAccess} method
   355      *          denies access to remove this provider's properties.
   362      *          denies access to remove this provider's properties.
   356      *
   363      *
   357      * @since 1.2
   364      * @since 1.2
   358      */
   365      */
       
   366     @Override
   359     public synchronized Object remove(Object key) {
   367     public synchronized Object remove(Object key) {
   360         check("removeProviderProperty."+name);
   368         check("removeProviderProperty."+name);
   361         if (debug != null) {
   369         if (debug != null) {
   362             debug.println("Remove " + name + " provider property " + key);
   370             debug.println("Remove " + name + " provider property " + key);
   363         }
   371         }
   364         return implRemove(key);
   372         return implRemove(key);
   365     }
   373     }
   366 
   374 
       
   375     /**
       
   376      * Removes the entry for the specified key only if it is currently
       
   377      * mapped to the specified value.
       
   378      *
       
   379      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
       
   380      * method is called with the string {@code "removeProviderProperty."+name},
       
   381      * where {@code name} is the provider name, to see if it's ok to remove this
       
   382      * provider's properties.
       
   383      *
       
   384      * @throws  SecurityException
       
   385      *          if a security manager exists and its {@link
       
   386      *          java.lang.SecurityManager#checkSecurityAccess} method
       
   387      *          denies access to remove this provider's properties.
       
   388      */
       
   389     @Override
       
   390     public synchronized boolean remove(Object key, Object value) {
       
   391         check("removeProviderProperty."+name);
       
   392         if (debug != null) {
       
   393             debug.println("Remove " + name + " provider property " + key);
       
   394         }
       
   395         return implRemove(key, value);
       
   396     }
       
   397 
       
   398     /**
       
   399      * Replaces the entry for the specified key only if currently
       
   400      * mapped to the specified value.
       
   401      *
       
   402      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
       
   403      * method is called with the string {@code "putProviderProperty."+name},
       
   404      * where {@code name} is the provider name, to see if it's ok to set this
       
   405      * provider's property values.
       
   406      *
       
   407      * @throws  SecurityException
       
   408      *          if a security manager exists and its {@link
       
   409      *          java.lang.SecurityManager#checkSecurityAccess} method
       
   410      *          denies access to set property values.
       
   411      */
       
   412     @Override
       
   413     public synchronized boolean replace(Object key, Object oldValue,
       
   414             Object newValue) {
       
   415         check("putProviderProperty." + name);
       
   416 
       
   417         if (debug != null) {
       
   418             debug.println("Replace " + name + " provider property " + key);
       
   419         }
       
   420         return implReplace(key, oldValue, newValue);
       
   421     }
       
   422 
       
   423     /**
       
   424      * Replaces the entry for the specified key only if it is
       
   425      * currently mapped to some value.
       
   426      *
       
   427      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
       
   428      * method is called with the string {@code "putProviderProperty."+name},
       
   429      * where {@code name} is the provider name, to see if it's ok to set this
       
   430      * provider's property values.
       
   431      *
       
   432      * @throws  SecurityException
       
   433      *          if a security manager exists and its {@link
       
   434      *          java.lang.SecurityManager#checkSecurityAccess} method
       
   435      *          denies access to set property values.
       
   436      */
       
   437     @Override
       
   438     public synchronized Object replace(Object key, Object value) {
       
   439         check("putProviderProperty." + name);
       
   440 
       
   441         if (debug != null) {
       
   442             debug.println("Replace " + name + " provider property " + key);
       
   443         }
       
   444         return implReplace(key, value);
       
   445     }
       
   446 
       
   447     /**
       
   448      * Replaces each entry's value with the result of invoking the given
       
   449      * function on that entry, in the order entries are returned by an entry
       
   450      * set iterator, until all entries have been processed or the function
       
   451      * throws an exception.
       
   452      *
       
   453      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
       
   454      * method is called with the string {@code "putProviderProperty."+name},
       
   455      * where {@code name} is the provider name, to see if it's ok to set this
       
   456      * provider's property values.
       
   457      *
       
   458      * @throws  SecurityException
       
   459      *          if a security manager exists and its {@link
       
   460      *          java.lang.SecurityManager#checkSecurityAccess} method
       
   461      *          denies access to set property values.
       
   462      */
       
   463     @Override
       
   464     public synchronized void replaceAll(BiFunction<? super Object, ? super Object, ? extends Object> function) {
       
   465         check("putProviderProperty." + name);
       
   466 
       
   467         if (debug != null) {
       
   468             debug.println("ReplaceAll " + name + " provider property ");
       
   469         }
       
   470         implReplaceAll(function);
       
   471     }
       
   472 
       
   473     /**
       
   474      * Attempts to compute a mapping for the specified key and its
       
   475      * current mapped value (or {@code null} if there is no current
       
   476      * mapping).
       
   477      *
       
   478      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
       
   479      * method is called with the strings {@code "putProviderProperty."+name}
       
   480      * and {@code "removeProviderProperty."+name}, where {@code name} is the
       
   481      * provider name, to see if it's ok to set this provider's property values
       
   482      * and remove this provider's properties.
       
   483      *
       
   484      * @throws  SecurityException
       
   485      *          if a security manager exists and its {@link
       
   486      *          java.lang.SecurityManager#checkSecurityAccess} method
       
   487      *          denies access to set property values or remove properties.
       
   488      */
       
   489     @Override
       
   490     public synchronized Object compute(Object key,
       
   491         BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
       
   492         check("putProviderProperty." + name);
       
   493         check("removeProviderProperty" + name);
       
   494 
       
   495         if (debug != null) {
       
   496             debug.println("Compute " + name + " provider property " + key);
       
   497         }
       
   498         return implCompute(key, remappingFunction);
       
   499     }
       
   500 
       
   501     /**
       
   502      * If the specified key is not already associated with a value (or
       
   503      * is mapped to {@code null}), attempts to compute its value using
       
   504      * the given mapping function and enters it into this map unless
       
   505      * {@code null}.
       
   506      *
       
   507      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
       
   508      * method is called with the strings {@code "putProviderProperty."+name}
       
   509      * and {@code "removeProviderProperty."+name}, where {@code name} is the
       
   510      * provider name, to see if it's ok to set this provider's property values
       
   511      * and remove this provider's properties.
       
   512      *
       
   513      * @throws  SecurityException
       
   514      *          if a security manager exists and its {@link
       
   515      *          java.lang.SecurityManager#checkSecurityAccess} method
       
   516      *          denies access to set property values and remove properties.
       
   517      */
       
   518     @Override
       
   519     public synchronized Object computeIfAbsent(Object key, Function<? super Object, ? extends Object> mappingFunction) {
       
   520         check("putProviderProperty." + name);
       
   521         check("removeProviderProperty" + name);
       
   522 
       
   523         if (debug != null) {
       
   524             debug.println("ComputeIfAbsent " + name + " provider property " +
       
   525                     key);
       
   526         }
       
   527         return implComputeIfAbsent(key, mappingFunction);
       
   528     }
       
   529 
       
   530     /**
       
   531      * If the value for the specified key is present and non-null, attempts to
       
   532      * compute a new mapping given the key and its current mapped value.
       
   533      *
       
   534      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
       
   535      * method is called with the strings {@code "putProviderProperty."+name}
       
   536      * and {@code "removeProviderProperty."+name}, where {@code name} is the
       
   537      * provider name, to see if it's ok to set this provider's property values
       
   538      * and remove this provider's properties.
       
   539      *
       
   540      * @throws  SecurityException
       
   541      *          if a security manager exists and its {@link
       
   542      *          java.lang.SecurityManager#checkSecurityAccess} method
       
   543      *          denies access to set property values or remove properties.
       
   544      */
       
   545     @Override
       
   546     public synchronized Object computeIfPresent(Object key, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
       
   547         check("putProviderProperty." + name);
       
   548         check("removeProviderProperty" + name);
       
   549 
       
   550         if (debug != null) {
       
   551             debug.println("ComputeIfPresent " + name + " provider property " +
       
   552                     key);
       
   553         }
       
   554         return implComputeIfPresent(key, remappingFunction);
       
   555     }
       
   556 
       
   557     /**
       
   558      * If the specified key is not already associated with a value or is
       
   559      * associated with null, associates it with the given value. Otherwise,
       
   560      * replaces the value with the results of the given remapping function,
       
   561      * or removes if the result is null. This method may be of use when
       
   562      * combining multiple mapped values for a key.
       
   563      *
       
   564      * <p>If a security manager is enabled, its {@code checkSecurityAccess}
       
   565      * method is called with the strings {@code "putProviderProperty."+name}
       
   566      * and {@code "removeProviderProperty."+name}, where {@code name} is the
       
   567      * provider name, to see if it's ok to set this provider's property values
       
   568      * and remove this provider's properties.
       
   569      *
       
   570      * @throws  SecurityException
       
   571      *          if a security manager exists and its {@link
       
   572      *          java.lang.SecurityManager#checkSecurityAccess} method
       
   573      *          denies access to set property values or remove properties.
       
   574      */
       
   575     @Override
       
   576     public synchronized Object merge(Object key, Object value,  BiFunction<? super Object, ? super Object, ? extends Object>  remappingFunction) {
       
   577         check("putProviderProperty." + name);
       
   578         check("removeProviderProperty" + name);
       
   579 
       
   580         if (debug != null) {
       
   581             debug.println("Merge " + name + " provider property " + key);
       
   582         }
       
   583         return implMerge(key, value, remappingFunction);
       
   584     }
       
   585 
   367     // let javadoc show doc from superclass
   586     // let javadoc show doc from superclass
       
   587     @Override
   368     public Object get(Object key) {
   588     public Object get(Object key) {
   369         checkInitialized();
   589         checkInitialized();
   370         return super.get(key);
   590         return super.get(key);
   371     }
   591     }
   372 
   592 
       
   593     @Override
       
   594     public synchronized Object getOrDefault(Object key, Object defaultValue) {
       
   595         checkInitialized();
       
   596         return super.getOrDefault(key, defaultValue);
       
   597     }
       
   598 
       
   599     @Override
       
   600     public synchronized void forEach(BiConsumer<? super Object, ? super Object> action) {
       
   601         checkInitialized();
       
   602         super.forEach(action);
       
   603     }
       
   604 
   373     // let javadoc show doc from superclass
   605     // let javadoc show doc from superclass
       
   606     @Override
   374     public Enumeration<Object> keys() {
   607     public Enumeration<Object> keys() {
   375         checkInitialized();
   608         checkInitialized();
   376         return super.keys();
   609         return super.keys();
   377     }
   610     }
   378 
   611 
   379     // let javadoc show doc from superclass
   612     // let javadoc show doc from superclass
       
   613     @Override
   380     public Enumeration<Object> elements() {
   614     public Enumeration<Object> elements() {
   381         checkInitialized();
   615         checkInitialized();
   382         return super.elements();
   616         return super.elements();
   383     }
   617     }
   384 
   618 
   444         implClear();
   678         implClear();
   445         initialized = true;
   679         initialized = true;
   446         putAll(copy);
   680         putAll(copy);
   447     }
   681     }
   448 
   682 
       
   683     private boolean checkLegacy(Object key) {
       
   684         String keyString = (String)key;
       
   685         if (keyString.startsWith("Provider.")) {
       
   686             return false;
       
   687         }
       
   688 
       
   689         legacyChanged = true;
       
   690         if (legacyStrings == null) {
       
   691             legacyStrings = new LinkedHashMap<String,String>();
       
   692         }
       
   693         return true;
       
   694     }
       
   695 
   449     /**
   696     /**
   450      * Copies all of the mappings from the specified Map to this provider.
   697      * Copies all of the mappings from the specified Map to this provider.
   451      * Internal method to be called AFTER the security check has been
   698      * Internal method to be called AFTER the security check has been
   452      * performed.
   699      * performed.
   453      */
   700      */
   457         }
   704         }
   458     }
   705     }
   459 
   706 
   460     private Object implRemove(Object key) {
   707     private Object implRemove(Object key) {
   461         if (key instanceof String) {
   708         if (key instanceof String) {
   462             String keyString = (String)key;
   709             if (!checkLegacy(key)) {
   463             if (keyString.startsWith("Provider.")) {
       
   464                 return null;
   710                 return null;
   465             }
   711             }
   466             legacyChanged = true;
   712             legacyStrings.remove((String)key);
   467             if (legacyStrings == null) {
       
   468                 legacyStrings = new LinkedHashMap<String,String>();
       
   469             }
       
   470             legacyStrings.remove(keyString);
       
   471         }
   713         }
   472         return super.remove(key);
   714         return super.remove(key);
       
   715     }
       
   716 
       
   717     private boolean implRemove(Object key, Object value) {
       
   718         if (key instanceof String && value instanceof String) {
       
   719             if (!checkLegacy(key)) {
       
   720                 return false;
       
   721             }
       
   722             legacyStrings.remove((String)key, value);
       
   723         }
       
   724         return super.remove(key, value);
       
   725     }
       
   726 
       
   727     private boolean implReplace(Object key, Object oldValue, Object newValue) {
       
   728         if ((key instanceof String) && (oldValue instanceof String) &&
       
   729                 (newValue instanceof String)) {
       
   730             if (!checkLegacy(key)) {
       
   731                 return false;
       
   732             }
       
   733             legacyStrings.replace((String)key, (String)oldValue,
       
   734                     (String)newValue);
       
   735         }
       
   736         return super.replace(key, oldValue, newValue);
       
   737     }
       
   738 
       
   739     private Object implReplace(Object key, Object value) {
       
   740         if ((key instanceof String) && (value instanceof String)) {
       
   741             if (!checkLegacy(key)) {
       
   742                 return null;
       
   743             }
       
   744             legacyStrings.replace((String)key, (String)value);
       
   745         }
       
   746         return super.replace(key, value);
       
   747     }
       
   748 
       
   749     private void implReplaceAll(BiFunction<? super Object, ? super Object, ? extends Object> function) {
       
   750         legacyChanged = true;
       
   751         if (legacyStrings == null) {
       
   752             legacyStrings = new LinkedHashMap<String,String>();
       
   753         } else {
       
   754             legacyStrings.replaceAll((BiFunction<? super String, ? super String, ? extends String>) function);
       
   755         }
       
   756         super.replaceAll(function);
       
   757     }
       
   758 
       
   759 
       
   760     private Object implMerge(Object key, Object value, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
       
   761         if ((key instanceof String) && (value instanceof String)) {
       
   762             if (!checkLegacy(key)) {
       
   763                 return null;
       
   764             }
       
   765             legacyStrings.merge((String)key, (String)value,
       
   766                     (BiFunction<? super String, ? super String, ? extends String>) remappingFunction);
       
   767         }
       
   768         return super.merge(key, value, remappingFunction);
       
   769     }
       
   770 
       
   771     private Object implCompute(Object key, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
       
   772         if (key instanceof String) {
       
   773             if (!checkLegacy(key)) {
       
   774                 return null;
       
   775             }
       
   776             legacyStrings.computeIfAbsent((String) key,
       
   777                     (Function<? super String, ? extends String>) remappingFunction);
       
   778         }
       
   779         return super.compute(key, remappingFunction);
       
   780     }
       
   781 
       
   782     private Object implComputeIfAbsent(Object key, Function<? super Object, ? extends Object> mappingFunction) {
       
   783         if (key instanceof String) {
       
   784             if (!checkLegacy(key)) {
       
   785                 return null;
       
   786             }
       
   787             legacyStrings.computeIfAbsent((String) key,
       
   788                     (Function<? super String, ? extends String>) mappingFunction);
       
   789         }
       
   790         return super.computeIfAbsent(key, mappingFunction);
       
   791     }
       
   792 
       
   793     private Object implComputeIfPresent(Object key, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
       
   794         if (key instanceof String) {
       
   795             if (!checkLegacy(key)) {
       
   796                 return null;
       
   797             }
       
   798             legacyStrings.computeIfPresent((String) key,
       
   799                     (BiFunction<? super String, ? super String, ? extends String>) remappingFunction);
       
   800         }
       
   801         return super.computeIfPresent(key, remappingFunction);
   473     }
   802     }
   474 
   803 
   475     private Object implPut(Object key, Object value) {
   804     private Object implPut(Object key, Object value) {
   476         if ((key instanceof String) && (value instanceof String)) {
   805         if ((key instanceof String) && (value instanceof String)) {
   477             String keyString = (String)key;
   806             if (!checkLegacy(key)) {
   478             if (keyString.startsWith("Provider.")) {
       
   479                 return null;
   807                 return null;
   480             }
   808             }
   481             legacyChanged = true;
   809             legacyStrings.put((String)key, (String)value);
   482             if (legacyStrings == null) {
       
   483                 legacyStrings = new LinkedHashMap<String,String>();
       
   484             }
       
   485             legacyStrings.put(keyString, (String)value);
       
   486         }
   810         }
   487         return super.put(key, value);
   811         return super.put(key, value);
       
   812     }
       
   813 
       
   814     private Object implPutIfAbsent(Object key, Object value) {
       
   815         if ((key instanceof String) && (value instanceof String)) {
       
   816             if (!checkLegacy(key)) {
       
   817                 return null;
       
   818             }
       
   819             legacyStrings.putIfAbsent((String)key, (String)value);
       
   820         }
       
   821         return super.putIfAbsent(key, value);
   488     }
   822     }
   489 
   823 
   490     private void implClear() {
   824     private void implClear() {
   491         if (legacyStrings != null) {
   825         if (legacyStrings != null) {
   492             legacyStrings.clear();
   826             legacyStrings.clear();