e_ews_connection_new_full (ESource *source,
			   const gchar *uri,
			   CamelEwsSettings *settings,
			   gboolean allow_connection_reuse)
{
	CamelNetworkSettings *network_settings;
	EEwsConnection *cnc;
	gchar *hash_key;
	gchar *user;

	if (source)
		g_return_val_if_fail (E_IS_SOURCE (source), NULL);
	g_return_val_if_fail (uri != NULL, NULL);
	g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);

	network_settings = CAMEL_NETWORK_SETTINGS (settings);
	user = camel_network_settings_dup_user (network_settings);
	hash_key = g_strdup_printf ("%s@%s", user, uri);
	g_free (user);

	g_mutex_lock (&connecting);

	/* search the connection in our hash table */
	if (allow_connection_reuse && loaded_connections_permissions != NULL) {
		cnc = g_hash_table_lookup (
			loaded_connections_permissions, hash_key);

		if (E_IS_EWS_CONNECTION (cnc) &&
		    !e_ews_connection_get_disconnected_flag (cnc)) {
			g_object_ref (cnc);

			g_free (hash_key);

			g_mutex_unlock (&connecting);
			return cnc;
		}
	}

	/* not found, so create a new connection */
	cnc = g_object_new (E_TYPE_EWS_CONNECTION,
		"settings", settings,
		"source", source,
		NULL);

	cnc->priv->uri = g_strdup (uri);
	cnc->priv->hash_key = hash_key;  /* takes ownership */

	g_free (cnc->priv->impersonate_user);
	if (camel_ews_settings_get_use_impersonation (settings)) {
		cnc->priv->impersonate_user = camel_ews_settings_dup_impersonate_user (settings);
		if (cnc->priv->impersonate_user && !*cnc->priv->impersonate_user) {
			g_free (cnc->priv->impersonate_user);
			cnc->priv->impersonate_user = NULL;
		}
	} else {
		cnc->priv->impersonate_user = NULL;
	}

	e_binding_bind_property (
		settings, "timeout",
		cnc->priv->soup_session, "timeout",
		G_BINDING_SYNC_CREATE);

	if (allow_connection_reuse) {
		/* add the connection to the loaded_connections_permissions hash table */
		if (loaded_connections_permissions == NULL)
			loaded_connections_permissions = g_hash_table_new_full (
				g_str_hash, g_str_equal,
				g_free, NULL);
		g_hash_table_insert (
			loaded_connections_permissions,
			g_strdup (cnc->priv->hash_key), cnc);
	}

	/* free memory */
	g_mutex_unlock (&connecting);
	return cnc;

}
e_ews_connection_new_full (ESource *source,
			   const gchar *uri,
			   CamelEwsSettings *settings,
			   gboolean allow_connection_reuse)
{
	CamelNetworkSettings *network_settings;
	EEwsConnection *cnc;
	gchar *hash_key;
	gchar *user;

	if (source)
		g_return_val_if_fail (E_IS_SOURCE (source), NULL);
	g_return_val_if_fail (uri != NULL, NULL);
	g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);

	network_settings = CAMEL_NETWORK_SETTINGS (settings);
	user = camel_network_settings_dup_user (network_settings);
	hash_key = g_strdup_printf ("%s@%s", user, uri);
	g_free (user);

	g_mutex_lock (&connecting);

	 
	if (allow_connection_reuse && loaded_connections_permissions != NULL) {
		cnc = g_hash_table_lookup (
			loaded_connections_permissions, hash_key);

		if (E_IS_EWS_CONNECTION (cnc) &&
		    !e_ews_connection_get_disconnected_flag (cnc)) {
			g_object_ref (cnc);

			g_free (hash_key);

			g_mutex_unlock (&connecting);
			return cnc;
		}
	}

	 
	cnc = g_object_new (E_TYPE_EWS_CONNECTION,
		"settings", settings,
		"source", source,
		NULL);

	cnc->priv->uri = g_strdup (uri);
	cnc->priv->hash_key = hash_key;   

	g_free (cnc->priv->impersonate_user);
	if (camel_ews_settings_get_use_impersonation (settings)) {
		cnc->priv->impersonate_user = camel_ews_settings_dup_impersonate_user (settings);
		if (cnc->priv->impersonate_user && !*cnc->priv->impersonate_user) {
			g_free (cnc->priv->impersonate_user);
			cnc->priv->impersonate_user = NULL;
		}
	} else {
		cnc->priv->impersonate_user = NULL;
	}

	e_binding_bind_property (
		settings, "timeout",
		cnc->priv->soup_session, "timeout",
		G_BINDING_SYNC_CREATE);

	if (allow_connection_reuse) {
		 
		if (loaded_connections_permissions == NULL)
			loaded_connections_permissions = g_hash_table_new_full (
				g_str_hash, g_str_equal,
				g_free, NULL);
		g_hash_table_insert (
			loaded_connections_permissions,
			g_strdup (cnc->priv->hash_key), cnc);
	}

	 
	g_mutex_unlock (&connecting);
	return cnc;

}