code: public synchronized FileDigester getFileDigester( String algorithm )
          throws NoSuchAlgorithmException
      {
          FileDigester digester = digesters.get( algorithm );
  
          if ( digester == null )
          {
              // Algorithms with custom digesters
              if ( CRC32FileDigester.ALGORITHM.equals( algorithm ) )
              {
                  digester = new CRC32FileDigester();
              }
              
              else if ( CksumFileDigester.ALGORITHM.equals( algorithm ) )
              {
                  digester = new CksumFileDigester();
              }
  
              // Default case: try to use Java Security providers.
              else
              {
                  // Try with the current providers.
                  try
                  {
                      digester = new MessageDigestFileDigester( algorithm );
                  }
                  catch ( NoSuchAlgorithmException e )
                  {
                      // If the algorithm is not supported by default providers, try with Bouncy Castle.
                      if ( Security.getProvider( BouncyCastleProvider.PROVIDER_NAME ) == null )
                      {
                          Security.addProvider( new BouncyCastleProvider() );
                          digester = new MessageDigestFileDigester( algorithm );
                      }
  
                      // If Bouncy Castle was already used, fail.
                      else
                      {
                          throw e;
                      }
                  }
              }
  
              digesters.put( algorithm, digester );
          }
  
          return digester;
      }
docs: Get an instance of {@link FileDigester} for the given checksum algorithm.
  
  @param algorithm the target checksum algorithm.
  @return an instance of {@link FileDigester}.
  @throws NoSuchAlgorithmException if the checksum algorithm is not supported or invalid.
  @see FileDigester