示例#1
0
		private Yield UpdateHelper(string id, string rev, IPlay aDoc, Result<IPlay> aResult)
		{
			//Check if a play with this id exists.
			Result<IPlay> validPlayResult = new Result<IPlay>();
			yield return thePlayDataMapper.Retrieve(aDoc.Id, validPlayResult);
			if (validPlayResult.Value == null)
			{
				aResult.Throw(new ArgumentException());
				yield break;
			}

			//Check if the current user has the update rights.
			if (!HasAuthorization(validPlayResult.Value))
			{
				aResult.Throw(new UnauthorizedAccessException());
				yield break;
			}

			//Check if the source in the play exist and are not null.
			Coroutine.Invoke(CheckSource, aDoc, new Result());

			//Update and return the updated play.
			Result<IPlay> playResult = new Result<IPlay>();
			yield return thePlayDataMapper.Update(id, rev, aDoc, playResult);
			aResult.Return(playResult.Value);
		}
        /// <summary>
        /// <para>Deletes a single configuration value from a given section in the
        /// CouchDB server configuration.</para>
        /// <para>(This method is asynchronous.)</para>
        /// </summary>
        /// <param name="section">The configuration section.</param>
        /// <param name="keyName">The name of the configuration key.</param>
        /// <param name="result"></param>
        /// <returns></returns>
        public Result DeleteConfigValue(
      string section, 
      string keyName, 
      Result result)
        {
            if (String.IsNullOrEmpty(section))
            throw new ArgumentException("section cannot be null nor empty");
              if (String.IsNullOrEmpty(keyName))
            throw new ArgumentException("keyName cannot be null nor empty");
              if (result == null)
            throw new ArgumentNullException("result");

              BasePlug
            .At(Constants._CONFIG, XUri.EncodeFragment(section),
            XUri.EncodeFragment(keyName))
            .Delete(DreamMessage.Ok(), new Result<DreamMessage>())
            .WhenDone(
              a =>
              {
            if (a.Status == DreamStatus.Ok)
              result.Return(); // remove " and "\n
            else
              result.Throw(new CouchException(a));
              },
              result.Throw
            );
              return result;
        }
示例#3
0
		private Yield CheckSource(IPlay aPlay, Result aResult)
		{
			//can't be null, it must have a source
			if (aPlay.SourceId == null)
			{
				aResult.Throw(new ArgumentException());
				yield break;
			}

			// if this source exists
			Result<bool> validSourceResult = new Result<bool>();
			yield return Context.Current.Instance.SourceController.Exists(aPlay.SourceId, validSourceResult);
			if (!validSourceResult.Value)
			{
				aResult.Throw(new ArgumentException());
				yield break;
			}
			aResult.Return();
		}
示例#4
0
        public Result<bool> Logoff(Result<bool> aResult)
        {
            if (aResult == null)
                throw new ArgumentNullException("aResult");

            BasePlug.At("_session").Delete(new Result<DreamMessage>()).WhenDone(
                a => {
                    if (a.Status == DreamStatus.Ok)
                        aResult.Return(true);
                    else
                        aResult.Throw(new CouchException(a));
                },
                aResult.Throw
            );
            return aResult;
        }
示例#5
0
		private Yield CreateHelper(IPlay aDoc, Result<IPlay> aResult)
		{
			//Check if user is set as we need to know the creator.
			if (Context.Current.User == null)
			{
				aResult.Throw(new UnauthorizedAccessException());
				yield break;
			}

			//Check that the sources aren't null and does exists
			yield return Coroutine.Invoke(CheckSource, aDoc, new Result());

			//Insert a the score and return
			Result<IPlay> resultCreate = new Result<IPlay>();
			yield return thePlayDataMapper.Create(aDoc, resultCreate);
			aResult.Return(resultCreate.Value);
		}
        /* =========================================================================
         * Asynchronous methods
         * =======================================================================*/
        /// <summary>
        /// <para>Adds an attachment to a document. The document revision must be 
        /// specified when using this method.</para>
        /// <para>(This method is asynchronous.)</para>
        /// </summary>
        /// <param name="id">ID of the CouchDB document.</param>
        /// <param name="rev">Revision of the CouchDB document.</param>
        /// <param name="attachment">Stream of the attachment. Will be closed once
        /// the request is sent.</param>
        /// <param name="attachmentLength">Length of the attachment stream.</param>
        /// <param name="fileName">Filename of the attachment.</param>
        /// <param name="contentType">Content type of the document.</param>
        /// <param name="result"></param>
        /// <returns></returns>
        public Result<JObject> AddAttachment(
      string id, 
      string rev, 
      Stream attachment, 
      long attachmentLength, 
      string fileName, 
      MimeType contentType, 
      Result<JObject> result)
        {
            if (String.IsNullOrEmpty(id))
            throw new ArgumentNullException("id");
              if (String.IsNullOrEmpty(rev))
            throw new ArgumentNullException("rev");
              if (attachment == null)
            throw new ArgumentNullException("attachment");
              if (attachmentLength < 0)
            throw new ArgumentOutOfRangeException("attachmentLength");
              if (String.IsNullOrEmpty(fileName))
            throw new ArgumentNullException("fileName");
              if (contentType == null)
            throw new ArgumentNullException("contentType");
              if (result == null)
            throw new ArgumentNullException("result");

              BasePlug
            .AtPath(XUri.EncodeFragment(id))
            .At(XUri.EncodeFragment(fileName))
            .With(Constants.REV, rev)
            .Put(DreamMessage.Ok(contentType, attachmentLength, attachment),
             new Result<DreamMessage>())
            .WhenDone(
              a =>
              {
            if (a.Status == DreamStatus.Created)
              result.Return(JObject.Parse(a.ToText()));
            else
              result.Throw(new CouchException(a));
              },
              result.Throw
            );

              return result;
        }
		public Result<User> GetUser(string username, Result<User> aResult)
		{
			theServiceUri.At("users", username)
				.Get(new Result<DreamMessage>())
				.WhenDone(delegate(Result<DreamMessage> answer)
				{
					if (!answer.Value.IsSuccessful)
					{
						if (answer.Value.Status == DreamStatus.NotFound)
							aResult.Return((User)null);
						aResult.Throw(answer.Exception);
					}
					else
					{
						aResult.Return(new User(JObject.Parse(answer.Value.ToText())));
					}
				}
				);
			return aResult;
		}
示例#8
0
        /* =========================================================================
         * Asynchronous methods
         * =======================================================================*/
        /// <summary>
        /// <para>Restarts the CouchDB instance. You must be authenticated as a user
        /// with administration privileges for this to work.</para>
        /// <para>(This method is asynchronous.)</para>
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public Result RestartServer(Result result)
        {
            if (result == null)
            throw new ArgumentNullException("result");

              BasePlug
            .At(Constants._RESTART)
            .Post(DreamMessage.Ok(MimeType.JSON, String.Empty),
              new Result<DreamMessage>())
            .WhenDone(
              a =>
              {
            if (a.Status == DreamStatus.Ok)
              result.Return();
            else
              result.Throw(new CouchException(a));
              },
              result.Throw
            );
              return result;
        }
		public Result<bool> BulkFascimile(string sourceId, Stream file, Result<bool> aResult)
		{
			theServiceUri
				.At("sources",sourceId,"fascimiles")
				.Post(DreamMessage.Ok(new MimeType("application/zip"), file.Length, file),new Result<DreamMessage>())
				.WhenDone(delegate(Result<DreamMessage> answer)
				{
					if (!answer.Value.IsSuccessful)
					{
						if (answer.Value.Status == DreamStatus.BadRequest)
							aResult.Return(false);
						else
							aResult.Throw(answer.Exception);
					}
					else
					{
						aResult.Return(true);
					}
				}
				);
			return aResult;
		}
示例#10
0
        public Result<bool> IsLogged(Result<bool> aResult)
        {
            if (aResult == null)
                throw new ArgumentNullException("aResult");

            BasePlug.At("_session").Get(new Result<DreamMessage>()).WhenDone(
                a =>
                {
                    if (a.Status == DreamStatus.Ok)
                    {
                        JObject user = JObject.Parse(a.ToText());
                        aResult.Return(user["info"]["authenticated"] != null);
                    }
                    else
                    {
                        aResult.Throw(new CouchException(a));
                    }
                },
                aResult.Throw
            );
            return aResult;
        }
示例#11
0
        /// <summary>
        /// Creates a database
        /// </summary>
        /// <param name="aDatabaseName">Name of new database</param>
        /// <param name="aResult"></param>
        /// <returns></returns>
        public Result<JObject> CreateDatabase(string aDatabaseName, Result<JObject> aResult)
        {
            if (String.IsNullOrEmpty(aDatabaseName))
                throw new ArgumentException("DatabaseName cannot be null nor empty");
            if (aResult == null)
                throw new ArgumentNullException("aResult");

            BasePlug.At(XUri.EncodeFragment(aDatabaseName)).Put(DreamMessage.Ok(), new Result<DreamMessage>()).WhenDone(
                a =>
                {
                    if (a.Status == DreamStatus.Created)
                    {
                        aResult.Return(JObject.Parse(a.ToText()));
                    }
                    else
                    {
                        aResult.Throw(new CouchException(a));
                    }
                },
                aResult.Throw
            );
            return aResult;
        }
        /// <summary>
        /// <para>Deletes the specified database.</para>
        /// <para>(This method is asynchronous.)</para>
        /// </summary>
        /// <param name="databaseName">Name of the database to delete.</param>
        /// <param name="result"></param>
        /// <returns></returns>
        public Result<JObject> DeleteDatabase(
      string databaseName, 
      Result<JObject> result)
        {
            if (String.IsNullOrEmpty(databaseName))
            throw new ArgumentException("databaseName cannot be null nor empty");
              if (result == null)
            throw new ArgumentNullException("result");

              BasePlug
            .At(XUri.EncodeFragment(databaseName))
            .Delete(new Result<DreamMessage>())
            .WhenDone(
              a =>
              {
            if (a.Status == DreamStatus.Ok)
              result.Return(JObject.Parse(a.ToText()));
            else
              result.Throw(new CouchException(a));
              },
              result.Throw
            );
              return result;
        }
示例#13
0
        private Yield LoadContactsHelper(Result<ViewResult<string,string, Contact>> aResult)
        {
            Result<bool> exists = new Result<bool>();
            yield return theDatabase.DocumentExists("_design/contactview", exists);

            if(exists.HasException){
                aResult.Throw(exists.Exception);
                yield break;
            }

            if (!exists.Value)
            {
                CouchDesignDocument view = new CouchDesignDocument("contactview");
                view.Views.Add("all",
                               new CouchView(
                                  @"function(doc){
                                       if(doc.type && doc.type == 'contact'){
                                          emit(doc.lastName, doc.firstName)
                                       }
                                    }"));

                Result<CouchDesignDocument> creationResult = new Result<CouchDesignDocument>();
                yield return theDatabase.CreateDocument(view, creationResult);

                if(creationResult.HasException)
                {
                    aResult.Throw(creationResult.Exception);
                    yield break;
                }
            }

            var viewRes = new Result<ViewResult<string, string, Contact>>();
            yield return theDatabase.GetView("contactview", "all",viewRes);

            if(viewRes.HasException)
            {
                aResult.Throw(viewRes.Exception);
                yield break;
            }
            aResult.Return(viewRes.Value);
        }
示例#14
0
		private Yield DeleteHelper(string id, string rev, Result<bool> aResult)
		{
			//Check if a source with this id exists.
			Result<ISource> validSourceResult = new Result<ISource>();
			yield return theSourceDataMapper.Retrieve(id, validSourceResult);
			if (validSourceResult.Value == null)
			{
				aResult.Throw(new ArgumentException(String.Format("Source not found for id '{0}'", id)));
				yield break;
			}

			yield return theSourceDataMapper.Delete(id, rev ?? validSourceResult.Value.Rev, aResult);
		}
        private Result<IssueData[]> ProcessIssueBatch(ElasticThreadPool pool,  string projectId, string filterId, int pageNumber, int issuesInBatch, Tuplet<bool> canceled, Result<IssueData[]> result) {
            pool.QueueWorkItem(HandlerUtil.WithEnv(delegate {

                // TODO (steveb): use result.IsCanceled instead of shared tuple once cancellation is supported on the result object

                // check if request has been canceled
                if(!canceled.Item1) {
                    IssueData[] issuesForBatch;
                    if(!string.IsNullOrEmpty(filterId)) {
                        issuesForBatch = _service.mc_filter_get_issues(_username, _password, projectId, filterId, pageNumber.ToString(), issuesInBatch.ToString());
                    } else {
                        issuesForBatch = _service.mc_project_get_issues(_username, _password, projectId, pageNumber.ToString(), issuesInBatch.ToString());
                    }
                    result.Return(issuesForBatch);
                } else {
                	
                	// TODO (steveb): throw a more specific exception
                    result.Throw(new Exception("unspecified error"));
                }
            },TaskEnv.Clone()));
            return result;
        } 
示例#16
0
        private Result Write(Action<string> activity, Stream stream, byte[] buffer, int offset, int count, Result result)
        {
            // asynchronously execute read operation
            Result<IAsyncResult> inner = new Result<IAsyncResult>(TimeSpan.MaxValue);
            inner.WhenDone(delegate(Result<IAsyncResult> _unused) {
                try {
                    activity(string.Format("pre {0}!EndWrite", stream.GetType().FullName));
                    stream.EndWrite(inner.Value);
                    activity("post EndWrite");
                    result.Return();
                } catch(Exception e) {
                    activity("throw Write 1");
                    result.Throw(e);
                }
            });
            try {
                activity(string.Format("pre {0}!BeginWrite", stream.GetType().FullName));
                stream.BeginWrite(buffer, offset, count, inner.Return, stream);
                activity("post BeginWrite");
            } catch(Exception e) {
                activity("throw Write 2");
                result.Throw(e);
            }

            // return yield handle
            return result;
        }
示例#17
0
		private Yield UpdateHelper(string id, string rev, ISource aDoc, Result<ISource> aResult)
		{
			//Check if a source with this id exists.
			Result<ISource> validSourceResult = new Result<ISource>();
			yield return theSourceDataMapper.Retrieve(id, validSourceResult);
			if (validSourceResult.Value == null)
			{
				aResult.Throw(new ArgumentException(String.Format("Source not found for id '{0}'",id)));
				yield break;
			}

			//Update and return the updated source.
			Result<ISource> sourceResult = new Result<ISource>();
			yield return theSourceDataMapper.Update(id, rev ?? validSourceResult.Value.Rev , aDoc, sourceResult);
			aResult.Return(sourceResult.Value);
		}
示例#18
0
        public Result<JObject> TriggerReplication(ReplicationOptions aReplicationOptions, Result<JObject> aResult)
        {
            if (aReplicationOptions == null)
                throw new ArgumentNullException("aReplicationOptions");
            if (aResult == null)
                throw new ArgumentNullException("aResult");

            Plug p = BasePlug.At(Constants.REPLICATE);

            string json = aReplicationOptions.ToString();
            p.Post(DreamMessage.Ok(MimeType.JSON, json), new Result<DreamMessage>()).WhenDone(
                a =>
                {
                    if((a.Status == DreamStatus.Accepted)||
                       (a.Status == DreamStatus.Ok))
                    {
                        aResult.Return(JObject.Parse(a.ToText()));
                    }
                    else
                    {
                        aResult.Throw(new CouchException(a));
                    }
                },
                aResult.Throw
            );

            return aResult;
        }
示例#19
0
		private Yield UpdateHelper(string id, string rev, IScore aDoc, Result<IScore> aResult)
		{
			//Check if a score with this id exists.
			Result<IScore> validScoreResult = new Result<IScore>();
			yield return theScoreDataMapper.Retrieve(aDoc.Id, validScoreResult);
			if (validScoreResult.Value == null)
			{
				aResult.Throw(new ArgumentException());
				yield break;
			}

			//Check if the sources in the score exists and are not null.
			Coroutine.Invoke(CheckSources, aDoc, new Result());

			//Update and return the updated score.
			Result<IScore> scoreResult = new Result<IScore>();
			yield return theScoreDataMapper.Update(id, rev, aDoc, scoreResult);
			aResult.Return(scoreResult.Value);
		}
示例#20
0
		private Yield GetPlaysFromSourceHelper(int offset, int max, string aSourceId, Result<SearchResult<IPlay>> aResult)
		{
			//Check if the play exists
			Result<bool> resultExists = new Result<bool>();
			yield return Context.Current.Instance.SourceController.Exists(aSourceId, resultExists);
			if (resultExists.Value)
			{
				//Get the plays that have this source id as textual or musical source.
				Result<SearchResult<IPlay>> resultSearch = new Result<SearchResult<IPlay>>();
				yield return thePlayDataMapper.GetPlaysFromSource(offset, max, aSourceId, resultSearch);
				aResult.Return(resultSearch.Value);
			}
			else
				aResult.Throw(new DreamNotFoundException("Source not found"));
		}
示例#21
0
        public Result<Dictionary<string, Dictionary<string, string>>> GetConfig(Result<Dictionary<string, Dictionary<string, string>>> aResult)
        {
            if (aResult == null)
                throw new ArgumentNullException("aResult");

            BasePlug.At(Constants.CONFIG).Get(DreamMessage.Ok(), new Result<DreamMessage>()).WhenDone(
                a =>
                {
                    if (a.Status == DreamStatus.Ok)
                        aResult.Return(JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(a.ToText()));
                    else
                        aResult.Throw(new CouchException(a));
                },
                aResult.Throw
            );
            return aResult;
        }
示例#22
0
        /// <summary>
        /// Perform Cookie base authentication with given username and password
        /// Resulting cookie will be automatically used for all subsequent requests
        /// </summary>
        /// <param name="aUserName">User Name</param>
        /// <param name="aPassword">Password</param>
        /// <param name="aResult"></param>
        /// <returns>true if authentication succeed</returns>
        public Result<bool> Logon(string aUserName, string aPassword, Result<bool> aResult)
        {
            if (String.IsNullOrEmpty(aUserName))
                throw new ArgumentException("aUserName cannot be null nor empty");
            if (String.IsNullOrEmpty(aPassword))
                throw new ArgumentException("aPassword cannot be null nor empty");
            if (aResult == null)
                throw new ArgumentNullException("aResult");

            string content = String.Format("name={0}&password={1}", aUserName, aPassword);

            BasePlug.At("_session").Post(DreamMessage.Ok(MimeType.FORM_URLENCODED,content), new Result<DreamMessage>()).WhenDone(
                a => {
                    switch(a.Status)
                    {
                        case DreamStatus.Ok:
                            BasePlug.CookieJar.Update(a.Cookies, new XUri(BasePlug.Uri.SchemeHostPort));
                            BasePlug = BasePlug.WithHeader("X-CouchDB-WWW-Authenticate", "Cookie");
                            aResult.Return(true);
                            break;
                        default:
                            aResult.Throw(new CouchException(a));
                            break;
                    }
                },
                aResult.Throw
            );
            return aResult;
        }
示例#23
0
        private Result<DreamMessage> SubmitRequestAsync(string verb, XUri uri, IPrincipal user, DreamMessage request, Result<DreamMessage> response, Action completion)
        {
            if(string.IsNullOrEmpty(verb)) {
                if(completion != null) {
                    completion();
                }
                throw new ArgumentNullException("verb");
            }
            if(uri == null) {
                if(completion != null) {
                    completion();
                }
                throw new ArgumentNullException("uri");
            }
            if(request == null) {
                if(completion != null) {
                    completion();
                }
                throw new ArgumentNullException("request");
            }
            if(response == null) {
                if(completion != null) {
                    completion();
                }
                throw new ArgumentNullException("response");
            }

            // ensure environment is still running
            if(!IsRunning) {
                response.Return(DreamMessage.InternalError("host not running"));
                if(completion != null) {
                    completion();
                }
                return response;
            }

            try {
                Interlocked.Increment(ref _requestCounter);

                // check if we were not able to begin processing the request
                DreamMessage failed = BeginRequest(completion, uri, request);
                if(failed != null) {
                    response.Return(failed);
                    EndRequest(completion, uri, request);
                    return response;
                }

                // check if 'verb' is overwritten by a processing parameter
                verb = verb.ToUpperInvariant();
                string requestedVerb = (uri.GetParam(DreamInParam.VERB, null) ?? request.Headers.MethodOverride ?? verb).ToUpperInvariant();
                if(
                    verb.EqualsInvariant(Verb.POST) || (
                        verb.EqualsInvariant(Verb.GET) && (
                            requestedVerb.EqualsInvariant(Verb.OPTIONS) ||
                            requestedVerb.EqualsInvariant(Verb.HEAD)
                        )
                    )
                ) {
                    verb = requestedVerb;
                }

                // check if an origin was specified
                request.Headers.DreamOrigin = uri.GetParam(DreamInParam.ORIGIN, request.Headers.DreamOrigin);

                // check if a public uri is supplied
                XUri publicUri = XUri.TryParse(uri.GetParam(DreamInParam.URI, null) ?? request.Headers.DreamPublicUri);
                XUri transport = XUri.TryParse(request.Headers.DreamTransport) ?? uri.WithoutCredentialsPathQueryFragment();
                if(publicUri == null) {

                    // check if request is local
                    if(transport.Scheme.EqualsInvariantIgnoreCase("local")) {

                        // local:// uris with no public-uri specifier default to the configured public-uri
                        publicUri = _publicUri;
                    } else {

                        // check if the request was forwarded through Apache mod_proxy
                        string proxyOverride = uri.GetParam(DreamInParam.HOST, null);
                        if(string.IsNullOrEmpty(proxyOverride)) {
                            proxyOverride = request.Headers.ForwardedHost;
                        }
                        string serverPath = string.Join("/", transport.Segments);
                        if(proxyOverride != null) {

                            // request used an override, append path of public-uri
                            serverPath = string.Join("/", _publicUri.Segments);
                        }

                        // set the uri scheme based-on the incoming scheme and the override header
                        string scheme = transport.Scheme;
                        if("On".EqualsInvariantIgnoreCase(request.Headers.FrontEndHttps ?? "")) {
                            scheme = Scheme.HTTPS;
                        }
                        scheme = uri.GetParam(DreamInParam.SCHEME, scheme);

                        // set the host port
                        string hostPort = proxyOverride ?? request.Headers.Host ?? uri.HostPort;
                        publicUri = new XUri(string.Format("{0}://{1}", scheme, hostPort)).AtPath(serverPath);
                    }
                    request.Headers.DreamPublicUri = publicUri.ToString();
                }

                // set host header
                request.Headers.Host = publicUri.HostPort;

                // convert incoming uri to local://
                XUri localFeatureUri = uri.ChangePrefix(uri.WithoutPathQueryFragment(), _localMachineUri);

                // check if path begins with public uri path
                if((transport.Segments.Length > 0) && localFeatureUri.PathStartsWith(transport.Segments)) {
                    localFeatureUri = localFeatureUri.WithoutFirstSegments(transport.Segments.Length);
                }

                // check if the path is the application root and whether we have special behavior for that
                if(localFeatureUri.Path.IfNullOrEmpty("/") == "/") {
                    if(!string.IsNullOrEmpty(_rootRedirect)) {
                        localFeatureUri = localFeatureUri.AtAbsolutePath(_rootRedirect);
                    } else if(IsDebugEnv) {
                        localFeatureUri = localFeatureUri.AtAbsolutePath("/host/services");
                    }
                }

                // find the requested feature
                List<DreamFeature> features;
                lock(_features) {
                    features = _features.Find(localFeatureUri);
                }
                DreamFeature feature = null;
                if(features != null) {

                    // TODO (steveb): match the incoming mime-type to the feature's acceptable mime-types (mime-type overloading)

                    // match the request verb to the feature verb
                    foreach(DreamFeature entry in features) {
                        if((entry.Verb == "*") || entry.Verb.EqualsInvariant(verb)) {
                            feature = entry;
                            break;
                        }
                    }

                    // check if this is an OPTIONS request and there is no defined feature for it
                    if(verb.EqualsInvariant(Verb.OPTIONS) && ((feature == null) || feature.Verb.EqualsInvariant("*"))) {

                        // list all allowed methods
                        List<string> methods = new List<string>();
                        foreach(DreamFeature entry in features) {
                            if(!methods.Contains(entry.Verb)) {
                                methods.Add(entry.Verb);
                            }
                        }
                        methods.Sort(StringComparer.Ordinal.Compare);
                        DreamMessage result = DreamMessage.Ok();
                        result.Headers.Allow = string.Join(", ", methods.ToArray());
                        response.Return(result);

                        // decrease counter for external requests
                        EndRequest(completion, uri, request);
                        return response;
                    }
                }

                // check if a feature was found
                if(feature == null) {
                    DreamMessage result;

                    // check if any feature was found
                    if((features == null) || (features.Count == 0)) {
                        string msg = verb + " URI: " + uri.ToString(false) + " LOCAL: " + localFeatureUri.ToString(false) + " PUBLIC: " + publicUri + " TRANSPORT: " + transport;
                        _log.WarnMethodCall("ProcessRequest: feature not found", msg);
                        result = DreamMessage.NotFound("resource not found");
                    } else {
                        string msg = verb + " " + uri.ToString(false);
                        _log.WarnMethodCall("ProcessRequest: method not allowed", msg);
                        List<string> methods = new List<string>();
                        foreach(DreamFeature entry in features) {
                            if(!methods.Contains(entry.Verb)) {
                                methods.Add(entry.Verb);
                            }
                        }
                        methods.Sort(StringComparer.Ordinal.Compare);
                        result = DreamMessage.MethodNotAllowed(methods.ToArray(), "allowed methods are " + string.Join(", ", methods.ToArray()));
                    }
                    response.Return(result);

                    // decrease counter for external requests
                    EndRequest(completion, uri, request);
                    return response;
                }

                // add uri to aliases list
                if(_memorizeAliases) {
                    lock(_aliases) {
                        _aliases[transport] = transport;
                        _aliases[publicUri] = publicUri;
                    }
                }

                // create context
                DreamContext context = new DreamContext(this, verb, localFeatureUri, feature, publicUri, _publicUri, request, CultureInfo.InvariantCulture, GetRequestLifetimeScopeFactory(feature.Service));

                // attach request id to the context
                context.SetState(DreamHeaders.DREAM_REQUEST_ID, request.Headers.DreamRequestId);

                // add user to context
                context.User = user;

                // build linked-list of feature calls
                var chain = new Result<DreamMessage>(TimeSpan.MaxValue, TaskEnv.Current).WhenDone(result => {

                    // extract message
                    DreamMessage message;
                    if(result.HasValue) {
                        message = result.Value;
                    } else if(result.Exception is DreamAbortException) {
                        message = ((DreamAbortException)result.Exception).Response;
                    } else if(result.Exception is DreamCachedResponseException) {
                        message = ((DreamCachedResponseException)result.Exception).Response;
                    } else {
                        _log.ErrorExceptionFormat(response.Exception, "Failed Feature '{0}' Chain [{1}:{2}]: {3}",
                            feature.MainStage.Name,
                            verb,
                            localFeatureUri.Path,
                            response.Exception.Message
                        );
                        message = DreamMessage.InternalError(result.Exception);
                    }

                    // decrease counter for external requests
                    EndRequest(completion, uri, request);

                    // need to manually dispose of the context, since we're already attaching and detaching it by hand to TaskEnvs throughout the chain
                    if(response.IsCanceled) {
                        _log.DebugFormat("response for '{0}' has already returned", context.Uri.Path);
                        response.ConfirmCancel();
                        ((ITaskLifespan)context).Dispose();
                    } else {
                        ((ITaskLifespan)context).Dispose();
                        response.Return(message);
                    }
                });
                for(int i = feature.Stages.Length - 1; i >= 0; --i) {
                    var link = new DreamFeatureChain(feature.Stages[i], i == feature.MainStageIndex, context, chain, (i > 0) ? feature.Stages[i - 1].Name : "first");
                    chain = new Result<DreamMessage>(TimeSpan.MaxValue, TaskEnv.Current).WhenDone(link.Handler);
                }

                // kick-off new task
                AsyncUtil.Fork(
                    () => chain.Return(request),
                    TaskEnv.New(TimerFactory),
                    new Result(TimeSpan.MaxValue, response.Env).WhenDone(res => {
                        if(!res.HasException) {
                            return;
                        }
                        _log.ErrorExceptionFormat(res.Exception, "handler for {0}:{1} failed", context.Verb, context.Uri.ToString(false));
                        ((ITaskLifespan)context).Dispose();

                        // forward exception to recipient
                        response.Throw(res.Exception);

                        // decrease counter for external requests
                        EndRequest(completion, uri, request);
                    })
                );
            } catch(Exception e) {
                response.Throw(e);
                EndRequest(completion, uri, request);
            }
            return response;
        }
示例#24
0
        public Result<Dictionary<string, string>> GetConfigSection(string aSection, Result<Dictionary<string, string>> aResult)
        {
            if (aSection == null)
                throw new ArgumentNullException("aSection");
            if (aResult == null)
                throw new ArgumentNullException("aResult");
            if (String.IsNullOrEmpty(aSection))
                throw new ArgumentException("Section cannot be empty");

            BasePlug.At(Constants.CONFIG,XUri.EncodeFragment(aSection)).Get(DreamMessage.Ok(), new Result<DreamMessage>()).WhenDone(
                a =>
                {
                    switch(a.Status)
                    {
                        case DreamStatus.Ok:
                            aResult.Return(JsonConvert.DeserializeObject<Dictionary<string, string>>(a.ToText()));
                            break;
                        case DreamStatus.NotFound:
                            aResult.Return(new Dictionary<string, string>());
                            break;
                        default:
                            aResult.Throw(new CouchException(a));
                            break;
                    }
                },
                aResult.Throw
            );
            return aResult;
        }
示例#25
0
        public Result<string> GetConfigValue(string aSection, string aKeyName, Result<string> aResult)
        {
            if (String.IsNullOrEmpty(aSection))
                throw new ArgumentException("aSection cannot be null nor empty");
            if (String.IsNullOrEmpty(aKeyName))
                throw new ArgumentException("aKeyName cannot be null nor empty");
            if (aResult == null)
                throw new ArgumentNullException("aResult");

            BasePlug.At(Constants.CONFIG,XUri.EncodeFragment(aSection),XUri.EncodeFragment(aKeyName)).Get(DreamMessage.Ok(), new Result<DreamMessage>()).WhenDone(
                a =>
                    {
                        string value = a.ToText();
                        switch(a.Status)
                        {
                            case DreamStatus.Ok:
                                aResult.Return(value.Substring(1, value.Length - 3));// remove " and "\n
                                break;
                            case DreamStatus.NotFound:
                                aResult.Return((string)null);
                                break;
                            default:
                                aResult.Throw(new CouchException(a));
                                break;
                        }
                    },
                aResult.Throw
            );
            return aResult;
        }
 private void ReturnUserError(Exception exception, Result<DreamMessage> response) {
     var dreamException = exception as DreamResponseException;
     if(dreamException != null) {
         response.Throw(new DreamAbortException(dreamException.Response));
     } else if(exception is UserException) {
         response.Throw(new DreamBadRequestException(exception.Message));
     } else {
         response.Throw(exception);
     }
 }
示例#27
0
        //--- Methods ---
        /// <summary>
        /// Invoke the stage method.
        /// </summary>
        /// <param name="context"><see cref="DreamContext"/> for invocation.</param>
        /// <param name="request"><see cref="DreamMessage"/> for invocation.</param>
        /// <param name="response"><see cref="Result{DreamMessage}"/> for invocations.</param>
        public void Invoke(DreamContext context, DreamMessage request, Result<DreamMessage> response)
        {
            if(_handler != null) {
                Coroutine.Invoke(_handler, context, request, response);
            } else {
                try {

                    // build parameter list
                    var arguments = new object[_plan.Count];
                    for(int i = 0; i < _plan.Count; ++i) {
                        try {
                            arguments[i] = _plan[i].Invoke(context, request, response);
                        } catch(DreamException e) {
                            throw e;
                        } catch(Exception e) {
                            throw new FeatureArgumentParseException(_plan[i].ArgumentName, e);
                        }
                    }

                    // invoke method
                    if(_method.ReturnType == typeof(Yield)) {

                        // invoke method as coroutine
                        new Coroutine(_method, response).Invoke(() => (Yield)_method.InvokeWithRethrow(_service, arguments));
                    } else if(_method.ReturnType == typeof(XDoc)) {

                        // invoke method to get XDoc response (always an Ok)
                        var doc = _method.InvokeWithRethrow(_service, arguments) as XDoc;
                        response.Return(DreamMessage.Ok(doc));
                    } else {
                        response.Return((DreamMessage)_method.InvokeWithRethrow(_service, arguments));
                    }
                } catch(Exception e) {
                    response.Throw(e);
                }
            }
        }
示例#28
0
        /// <summary>
        /// Retrieve list of available databases on the server
        /// </summary>
        /// <param name="aResult"></param>
        /// <returns></returns>
        public Result<IEnumerable<string>> GetAllDatabases(Result<IEnumerable<string>> aResult)
        {
            if (aResult == null)
                throw new ArgumentNullException("aResult");

            BasePlug.At("_all_dbs").Get(new Result<DreamMessage>()).WhenDone(
                a =>
                    {
                        if (a.Status == DreamStatus.Ok)
                        {
                            var d = JArray.Parse(a.ToText());
                            aResult.Return(d.Values<string>());
                        }
                        else
                        {
                            aResult.Throw(new CouchException(a));
                        }
                    },
                aResult.Throw
            );

            return aResult;
        }
示例#29
0
        private Yield Memorize_Helper(long max, Result result) {

            // NOTE (steveb): this method is used to load an external stream into memory; this alleviates the problem of streams not being closed for simple operations

            if(max < 0) {
                max = long.MaxValue - 1;
            }

            // check if we already know that the stream will not fit
            long length = ContentLength;
            if(length > max) {

                // mark stream as closed
                _stream.Close();
                _stream = null;
                _streamOpen = false;

                // throw size exceeded exception
                result.Throw(new InternalBufferOverflowException("message body exceeded max size"));
                yield break;
            }
            if(length < 0) {
                length = long.MaxValue;
            }

            // NOTE: the content-length and body length may differ (e.g. HEAD verb)

            // copy contents asynchronously
            var buffer = new MemoryStream();
            Result<long> res;

            // TODO (steveb): use WithCleanup() to dispose of resources in case of failure
            yield return res = _stream.CopyToStream(buffer, Math.Min(length, max + 1), new Result<long>(TimeSpan.MaxValue)).Catch();

            // mark stream as closed
            _stream.Close();
            _stream = null;
            _streamOpen = false;

            // confirm successful outcome for asynchronous operation
            res.Confirm();
            if(buffer.Length > max) {
                result.Throw(new InternalBufferOverflowException("message body exceeded max size"));
                yield break;
            }
            buffer.Position = 0;
            _stream = buffer;
            result.Return();
        }
示例#30
0
        public Result SetConfigValue(string aSection, string aKeyName, string aValue, Result aResult)
        {
            if (String.IsNullOrEmpty(aSection))
                throw new ArgumentException("aSection cannot be null nor empty");
            if (String.IsNullOrEmpty(aKeyName))
                throw new ArgumentException("aKeyName cannot be null nor empty");
            if (aResult == null)
                throw new ArgumentNullException("aResult");

            if (aValue == null)
                return DeleteConfigValue(aSection, aKeyName, aResult);

            BasePlug.At(Constants.CONFIG, XUri.EncodeFragment(aSection), XUri.EncodeFragment(aKeyName)).Put(DreamMessage.Ok(MimeType.TEXT, "\"" + aValue + "\""), new Result<DreamMessage>()).WhenDone(
                a =>
                {
                    if (a.Status == DreamStatus.Ok)
                        aResult.Return();
                    else
                        aResult.Throw(new CouchException(a));
                },
                aResult.Throw
            );
            return aResult;
        }