private static string Uri(System.Uri u) { StringBuilder r = new StringBuilder(); r.Append(u.Scheme); r.Append("://"); r.Append(u.GetHost()); if (0 < u.Port) { if (u.Port == 80 && "http".Equals(u.Scheme)) { } else { if (u.Port == 443 && "https".Equals(u.Scheme)) { } else { r.Append(':').Append(u.Port); } } } r.Append(u.AbsolutePath); if (u.GetQuery() != null) { r.Append('?').Append(u.GetQuery()); } return(r.ToString()); }
/// <summary> /// Default constructor /// </summary> /// <param name="db">The local database to replicate to/from</param> /// <param name="remote">The remote Uri to sync with</param> /// <param name="continuous">If set to <c>true</c> continuous.</param> /// <param name="clientFactory">The client factory for instantiating the HttpClient used to create web requests</param> /// <param name="workExecutor">The TaskFactory to execute work on</param> protected Replication(Database db, Uri remote, bool continuous, IHttpClientFactory clientFactory, TaskFactory workExecutor) { LocalDatabase = db; Continuous = continuous; // NOTE: Consider running a separate scheduler for all http requests. WorkExecutor = workExecutor; CancellationTokenSource = new CancellationTokenSource(); RemoteUrl = remote; RequestHeaders = new Dictionary<String, Object>(); _requests = new ConcurrentDictionary<HttpRequestMessage, Task>(); // FIXME: Refactor to visitor pattern. if (RemoteUrl.GetQuery() != null && !StringEx.IsNullOrWhiteSpace(RemoteUrl.GetQuery())) { var uri = new Uri(remote.ToString()); var personaAssertion = URIUtils.GetQueryParameter(uri, PersonaAuthorizer.QueryParameter); if (personaAssertion != null && !StringEx.IsNullOrWhiteSpace(personaAssertion)) { var email = PersonaAuthorizer.RegisterAssertion(personaAssertion); var authorizer = new PersonaAuthorizer(email); Authenticator = authorizer; } var facebookAccessToken = URIUtils.GetQueryParameter(uri, FacebookAuthorizer.QueryParameter); if (facebookAccessToken != null && !StringEx.IsNullOrWhiteSpace(facebookAccessToken)) { var email = URIUtils.GetQueryParameter(uri, FacebookAuthorizer.QueryParameterEmail); var authorizer = new FacebookAuthorizer(email); Uri remoteWithQueryRemoved = null; try { remoteWithQueryRemoved = new UriBuilder(remote.Scheme, remote.GetHost(), remote.Port, remote.AbsolutePath).Uri; } catch (UriFormatException e) { throw new ArgumentException("Invalid URI format.", "remote", e); } FacebookAuthorizer.RegisterAccessToken(facebookAccessToken, email, remoteWithQueryRemoved.ToString()); Authenticator = authorizer; } // we need to remove the query from the URL, since it will cause problems when // communicating with sync gw / couchdb try { RemoteUrl = new UriBuilder(remote.Scheme, remote.GetHost(), remote.Port, remote.AbsolutePath).Uri; } catch (UriFormatException e) { throw new ArgumentException("Invalid URI format.", "remote", e); } } Batcher = new Batcher<RevisionInternal>(workExecutor, INBOX_CAPACITY, PROCESSOR_DELAY, inbox => { try { Log.V(TAG, "*** BEGIN ProcessInbox ({0} sequences)", inbox.Count); FireTrigger(ReplicationTrigger.Resume); ProcessInbox (new RevisionList(inbox)); Log.V(TAG, "*** END ProcessInbox (lastSequence={0})", LastSequence); } catch (Exception e) { Log.E(TAG, "ProcessInbox failed: ", e); throw new RuntimeException(e); } }); ClientFactory = clientFactory; _stateMachine = new StateMachine<ReplicationState, ReplicationTrigger>(ReplicationState.Initial); InitializeStateMachine(); }
/// <summary>Private Constructor</summary> protected Replication(Database db, Uri remote, bool continuous, IHttpClientFactory clientFactory, TaskFactory workExecutor) { LocalDatabase = db; Continuous = continuous; // NOTE: Consider running a separate scheduler for all http requests. WorkExecutor = workExecutor; CancellationTokenSource = new CancellationTokenSource(); RemoteUrl = remote; Status = ReplicationStatus.Stopped; online = Manager.SharedInstance.NetworkReachabilityManager.CurrentStatus == NetworkReachabilityStatus.Reachable; RequestHeaders = new Dictionary<String, Object>(); requests = new HashSet<HttpClient>(); // FIXME: Refactor to visitor pattern. if (RemoteUrl.GetQuery() != null && !RemoteUrl.GetQuery().IsEmpty()) { var uri = new Uri(remote.ToString()); var personaAssertion = URIUtils.GetQueryParameter(uri, PersonaAuthorizer.QueryParameter); if (personaAssertion != null && !personaAssertion.IsEmpty()) { var email = PersonaAuthorizer.RegisterAssertion(personaAssertion); var authorizer = new PersonaAuthorizer(email); Authenticator = authorizer; } var facebookAccessToken = URIUtils.GetQueryParameter(uri, FacebookAuthorizer.QueryParameter); if (facebookAccessToken != null && !facebookAccessToken.IsEmpty()) { var email = URIUtils.GetQueryParameter(uri, FacebookAuthorizer.QueryParameterEmail); var authorizer = new FacebookAuthorizer(email); Uri remoteWithQueryRemoved = null; try { remoteWithQueryRemoved = new UriBuilder(remote.Scheme, remote.GetHost(), remote.Port, remote.AbsolutePath).Uri; } catch (UriFormatException e) { throw new ArgumentException("Invalid URI format.", "remote", e); } FacebookAuthorizer.RegisterAccessToken(facebookAccessToken, email, remoteWithQueryRemoved.ToString()); Authenticator = authorizer; } // we need to remove the query from the URL, since it will cause problems when // communicating with sync gw / couchdb try { RemoteUrl = new UriBuilder(remote.Scheme, remote.GetHost(), remote.Port, remote.AbsolutePath).Uri; } catch (UriFormatException e) { throw new ArgumentException("Invalid URI format.", "remote", e); } } Batcher = new Batcher<RevisionInternal>(workExecutor, InboxCapacity, ProcessorDelay, inbox => { try { Log.V(Tag, "*** BEGIN ProcessInbox ({0} sequences)", inbox.Count); ProcessInbox (new RevisionList(inbox)); Log.V(Tag, "*** END ProcessInbox (lastSequence={0})", LastSequence); UpdateActive(); } catch (Exception e) { Log.E(Tag, "ERROR: ProcessInbox failed: ", e); throw new RuntimeException(e); } }); SetClientFactory(clientFactory); }
/// <summary>Construct a URIish from a standard URL.</summary> /// <remarks>Construct a URIish from a standard URL.</remarks> /// <param name="u">the source URL to convert from.</param> public URIish(Uri u) { scheme = u.Scheme; path = u.AbsolutePath; string ui = u.GetUserInfo(); if (ui != null) { int d = ui.IndexOf(':'); user = d < 0 ? ui : Sharpen.Runtime.Substring(ui, 0, d); pass = d < 0 ? null : Sharpen.Runtime.Substring(ui, d + 1); } port = u.Port; host = u.GetHost(); }
/// <summary>Private Constructor</summary> protected Replication(Database db, Uri remote, bool continuous, IHttpClientFactory clientFactory, TaskFactory workExecutor, CancellationTokenSource tokenSource = null) { LocalDatabase = db; Continuous = continuous; WorkExecutor = workExecutor; CancellationTokenSource = tokenSource ?? new CancellationTokenSource(); RemoteUrl = remote; Status = ReplicationStatus.Stopped; online = true; RequestHeaders = new Dictionary<String, Object>(); if (RemoteUrl.GetQuery() != null && !RemoteUrl.GetQuery().IsEmpty()) { var uri = new Uri(remote.ToString()); var personaAssertion = URIUtils.GetQueryParameter(uri, PersonaAuthorizer.QueryParameter); if (personaAssertion != null && !personaAssertion.IsEmpty()) { var email = PersonaAuthorizer.RegisterAssertion(personaAssertion); var authorizer = new PersonaAuthorizer(email); Authorizer = authorizer; } var facebookAccessToken = URIUtils.GetQueryParameter(uri, FacebookAuthorizer.QueryParameter); if (facebookAccessToken != null && !facebookAccessToken.IsEmpty()) { var email = URIUtils.GetQueryParameter(uri, FacebookAuthorizer.QueryParameterEmail); var authorizer = new FacebookAuthorizer(email); Uri remoteWithQueryRemoved = null; try { remoteWithQueryRemoved = new UriBuilder(remote.Scheme, remote.GetHost(), remote.Port, remote.AbsolutePath).Uri; } #if PORTABLE catch (FormatException e) #else catch (UriFormatException e) #endif { throw new ArgumentException("Invalid URI format.", "remote", e); } FacebookAuthorizer.RegisterAccessToken(facebookAccessToken, email, remoteWithQueryRemoved.ToString()); Authorizer = authorizer; } // we need to remove the query from the URL, since it will cause problems when // communicating with sync gw / couchdb try { RemoteUrl = new UriBuilder(remote.Scheme, remote.GetHost(), remote.Port, remote.AbsolutePath).Uri; } #if PORTABLE catch (FormatException e) #else catch (UriFormatException e) #endif { throw new ArgumentException("Invalid URI format.", "remote", e); } } Batcher = new Batcher<RevisionInternal>(workExecutor, InboxCapacity, ProcessorDelay, inbox => { Log.V (Database.Tag, "*** " + this + ": BEGIN processInbox (" + inbox.Count + " sequences)"); ProcessInbox (new RevisionList (inbox)); Log.V (Database.Tag, "*** " + this.ToString () + ": END processInbox (lastSequence=" + LastSequence); UpdateActive(); }, CancellationTokenSource); this.clientFactory = clientFactory ?? CouchbaseLiteHttpClientFactory.Instance; }