/** Creates a {@link FileSystem}. */
  protected FileSystem doCreateFileSystem(
      final FileName name, final FileSystemOptions fileSystemOptions) throws FileSystemException {
    // Create the file system
    final GenericFileName rootName = (GenericFileName) name;
    FileSystemOptions fsOpts =
        (fileSystemOptions == null) ? new FileSystemOptions() : fileSystemOptions;

    UserAuthenticationData authData = null;
    HttpClient httpClient;
    try {
      authData = UserAuthenticatorUtils.authenticate(fsOpts, AUTHENTICATOR_TYPES);

      httpClient =
          HttpClientFactory.createConnection(
              WebdavFileSystemConfigBuilder.getInstance(),
              "http",
              rootName.getHostName(),
              rootName.getPort(),
              UserAuthenticatorUtils.toString(
                  UserAuthenticatorUtils.getData(
                      authData,
                      UserAuthenticationData.USERNAME,
                      UserAuthenticatorUtils.toChar(rootName.getUserName()))),
              UserAuthenticatorUtils.toString(
                  UserAuthenticatorUtils.getData(
                      authData,
                      UserAuthenticationData.PASSWORD,
                      UserAuthenticatorUtils.toChar(rootName.getPassword()))),
              fsOpts);
    } finally {
      UserAuthenticatorUtils.cleanup(authData);
    }

    return new WebdavFileSystem(rootName, httpClient, fsOpts);
  }
  private FTPClient createClient() throws FileSystemException {
    final GenericFileName rootName = getRoot();

    UserAuthenticationData authData = null;
    try {
      authData =
          UserAuthenticatorUtils.authenticate(
              fileSystemOptions, FtpFileProvider.AUTHENTICATOR_TYPES);

      return FtpClientFactory.createConnection(
          rootName.getHostName(),
          rootName.getPort(),
          UserAuthenticatorUtils.getData(
              authData,
              UserAuthenticationData.USERNAME,
              UserAuthenticatorUtils.toChar(rootName.getUserName())),
          UserAuthenticatorUtils.getData(
              authData,
              UserAuthenticationData.PASSWORD,
              UserAuthenticatorUtils.toChar(rootName.getPassword())),
          rootName.getPath(),
          getFileSystemOptions());
    } finally {
      UserAuthenticatorUtils.cleanup(authData);
    }
  }
  /**
   * Creates a new connection to the server.
   *
   * @param builder The HttpFileSystemConfigBuilder.
   * @param scheme The protocol.
   * @param hostname The hostname.
   * @param port The port number.
   * @param username The username.
   * @param password The password
   * @param fileSystemOptions The file system options.
   * @return a new HttpClient connection.
   * @throws FileSystemException if an error occurs.
   * @since 2.0
   */
  public static HttpClient createConnection(
      HttpFileSystemConfigBuilder builder,
      String scheme,
      String hostname,
      int port,
      String username,
      String password,
      FileSystemOptions fileSystemOptions)
      throws FileSystemException {
    HttpClient client;
    try {
      HttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
      HttpConnectionManagerParams connectionMgrParams = mgr.getParams();

      client = new HttpClient(mgr);

      final HostConfiguration config = new HostConfiguration();
      config.setHost(hostname, port, scheme);

      if (fileSystemOptions != null) {
        String proxyHost = builder.getProxyHost(fileSystemOptions);
        int proxyPort = builder.getProxyPort(fileSystemOptions);

        if (proxyHost != null && proxyHost.length() > 0 && proxyPort > 0) {
          config.setProxy(proxyHost, proxyPort);
        }

        UserAuthenticator proxyAuth = builder.getProxyAuthenticator(fileSystemOptions);
        if (proxyAuth != null) {
          UserAuthenticationData authData =
              UserAuthenticatorUtils.authenticate(
                  proxyAuth,
                  new UserAuthenticationData.Type[] {
                    UserAuthenticationData.USERNAME, UserAuthenticationData.PASSWORD
                  });

          if (authData != null) {
            final UsernamePasswordCredentials proxyCreds =
                new UsernamePasswordCredentials(
                    UserAuthenticatorUtils.toString(
                        UserAuthenticatorUtils.getData(
                            authData, UserAuthenticationData.USERNAME, null)),
                    UserAuthenticatorUtils.toString(
                        UserAuthenticatorUtils.getData(
                            authData, UserAuthenticationData.PASSWORD, null)));

            AuthScope scope = new AuthScope(proxyHost, AuthScope.ANY_PORT);
            client.getState().setProxyCredentials(scope, proxyCreds);
          }

          if (builder.isPreemptiveAuth(fileSystemOptions)) {
            HttpClientParams httpClientParams = new HttpClientParams();
            httpClientParams.setAuthenticationPreemptive(true);
            client.setParams(httpClientParams);
          }
        }

        Cookie[] cookies = builder.getCookies(fileSystemOptions);
        if (cookies != null) {
          client.getState().addCookies(cookies);
        }
      }
      /**
       * ConnectionManager set methodsmust be called after the host & port and proxy host & port are
       * set in the HostConfiguration. They are all used as part of the key when
       * HttpConnectionManagerParams tries to locate the host configuration.
       */
      connectionMgrParams.setMaxConnectionsPerHost(
          config, builder.getMaxConnectionsPerHost(fileSystemOptions));
      connectionMgrParams.setMaxTotalConnections(builder.getMaxTotalConnections(fileSystemOptions));

      client.setHostConfiguration(config);

      if (username != null) {
        final UsernamePasswordCredentials creds =
            new UsernamePasswordCredentials(username, password);
        AuthScope scope = new AuthScope(hostname, AuthScope.ANY_PORT);
        client.getState().setCredentials(scope, creds);
      }

      client.executeMethod(new HeadMethod());
    } catch (final Exception exc) {
      throw new FileSystemException(
          "vfs.provider.http/connect.error", new Object[] {hostname}, exc);
    }

    return client;
  }