Esempio n. 1
0
        /// <summary>
        /// Generates a SPARQL Service Description Graph for the given Protocol Handler Configuration or uses the configuration supplied Description Graph
        /// </summary>
        /// <param name="context">HTTP Context</param>
        /// <param name="config">Protocol Handler Configuration</param>
        /// <param name="descripUri">Base URI of the Description</param>
        /// <returns></returns>
        public static IGraph GetServiceDescription(HttpContext context, BaseProtocolHandlerConfiguration config, Uri descripUri)
        {
            //Use user specified Service Description if present
            if (config.ServiceDescription != null)
            {
                return(config.ServiceDescription);
            }

            IGraph g = SparqlServiceDescriber.GetNewGraph();

            //Add the Top Level Node representing the Service
            IUriNode descrip = g.CreateUriNode(descripUri);
            IUriNode rdfType = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfType));
            IUriNode service = g.CreateUriNode("sd:" + ClassService);

            g.Assert(descrip, rdfType, service);

            //Add its sd:url
            IUriNode url = g.CreateUriNode("sd:" + PropertyUrl);

            g.Assert(descrip, url, descrip);

            //Add the Input Formats
            IUriNode inputFormat = g.CreateUriNode("sd:" + PropertyInputFormat);

            foreach (MimeTypeDefinition definition in MimeTypesHelper.Definitions)
            {
                if (definition.CanParseRdf)
                {
                    if (definition.FormatUri != null)
                    {
                        g.Assert(descrip, inputFormat, g.CreateUriNode(new Uri(definition.FormatUri)));
                    }
                }
            }

            //Add the Result Formats
            IUriNode resultFormat = g.CreateUriNode("sd:" + PropertyResultFormat);

            foreach (MimeTypeDefinition definition in MimeTypesHelper.Definitions)
            {
                if (definition.CanWriteRdf)
                {
                    if (definition.FormatUri != null)
                    {
                        g.Assert(descrip, resultFormat, g.CreateUriNode(new Uri(definition.FormatUri)));
                    }
                }
            }

            config.AddFeatureDescription(g, descrip);

            return(g);
        }
Esempio n. 2
0
 /// <summary>
 /// Processes Service Description requests
 /// </summary>
 /// <param name="context">HTTP Context</param>
 public void ProcessDescriptionRequest(HttpContext context)
 {
     try
     {
         //Get the Service Description Graph
         IGraph serviceDescrip = SparqlServiceDescriber.GetServiceDescription(context, this._config, new Uri(context.Request.Url.AbsoluteUri), ServiceDescriptionType.All);
         HandlerHelper.SendToClient(context, serviceDescrip, this._config);
     }
     catch
     {
         //If any errors occur then return a 500 Internal Server Error
         context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
     }
 }
Esempio n. 3
0
        /// <summary>
        /// Generates a SPARQL Service Description Graph for the given Update Handler Configuration or uses the configuration supplied Description Graph
        /// </summary>
        /// <param name="context">HTTP Context</param>
        /// <param name="config">Update Handler Configuration</param>
        /// <param name="descripUri">Base URI of the Description</param>
        /// <returns></returns>
        public static IGraph GetServiceDescription(HttpContext context, BaseUpdateHandlerConfiguration config, Uri descripUri)
        {
            //Use user specified Service Description if present
            if (config.ServiceDescription != null)
            {
                return(config.ServiceDescription);
            }

            IGraph g = SparqlServiceDescriber.GetNewGraph();

            //Add the Top Level Node representing the Service
            IUriNode descrip = g.CreateUriNode(descripUri);
            IUriNode rdfType = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfType));
            IUriNode service = g.CreateUriNode("sd:" + ClassService);

            g.Assert(descrip, rdfType, service);

            //Add its sd:url
            IUriNode url = g.CreateUriNode("sd:" + PropertyUrl);

            g.Assert(descrip, url, descrip);

            //Add the sd:supportedLanguage
            IUriNode supportedLang = g.CreateUriNode("sd:" + PropertySupportedLanguage);

            g.Assert(descrip, supportedLang, g.CreateUriNode("sd:" + InstanceSparql11Update));

            //Add Features and Dataset Description
            //First add descriptions for Global Expression Factories
            IUriNode extensionFunction  = g.CreateUriNode("sd:" + PropertyExtensionFunction);
            IUriNode extensionAggregate = g.CreateUriNode("sd:" + PropertyExtensionAggregate);

            foreach (ISparqlCustomExpressionFactory factory in SparqlExpressionFactory.Factories)
            {
                foreach (Uri u in factory.AvailableExtensionFunctions)
                {
                    g.Assert(descrip, extensionFunction, g.CreateUriNode(u));
                }
                foreach (Uri u in factory.AvailableExtensionAggregates)
                {
                    g.Assert(descrip, extensionAggregate, g.CreateUriNode(u));
                }
            }

            //Then get the Configuration Object to add any other Feature Descriptions it wishes to
            config.AddFeatureDescription(g, descrip);

            return(g);
        }
Esempio n. 4
0
        /// <summary>
        /// Processes requests
        /// </summary>
        /// <param name="context">HTTP Context</param>
        public void ProcessRequest(HttpContext context)
        {
            this._config = this.LoadConfig(context, out this._basePath);

            //Add our Standard Headers
            HandlerHelper.AddStandardHeaders(context, this._config);

            String path = context.Request.Path;

            if (path.StartsWith(this._basePath))
            {
                path = path.Substring(this._basePath.Length);
            }

            //OPTIONS requests always result in the Service Description document
            if (context.Request.HttpMethod.Equals("OPTIONS"))
            {
                IGraph svcDescrip = SparqlServiceDescriber.GetServiceDescription(context, this._config, new Uri(new Uri(context.Request.Url.AbsoluteUri), this._basePath + "description"), ServiceDescriptionType.All);
                HandlerHelper.SendToClient(context, svcDescrip, this._config);
            }
            else
            {
                //Otherwise determine the type of request based on the Path
                switch (path)
                {
                case "query":
                    this.ProcessQueryRequest(context);
                    break;

                case "update":
                    this.ProcessUpdateRequest(context);
                    break;

                case "description":
                    this.ProcessDescriptionRequest(context);
                    break;

                default:
                    this.ProcessProtocolRequest(context);
                    break;
                }
            }
        }
        /// <summary>
        /// Processes requests made to the Graph Store HTTP Protocol endpoint and invokes the appropriate methods on the Protocol Processor that is in use
        /// </summary>
        /// <param name="context">HTTP Context</param>
        /// <remarks>
        /// <para>
        /// Implementations may override this if necessary - if the implementation is only providing additional logic such as authentication, ACLs etc. then it is recommended that the override applies its logic and then calls the base method since this base method will handle much of the error handling and sending of appropriate HTTP Response Codes.
        /// </para>
        /// </remarks>
        public virtual void ProcessRequest(HttpContext context)
        {
            this._config = this.LoadConfig(context, out this._basePath);
            WebContext webContext = new WebContext(context);

            // Add our Standard Headers
            HandlerHelper.AddStandardHeaders(webContext, this._config);

            if (context.Request.HttpMethod.Equals("OPTIONS"))
            {
                // OPTIONS requests always result in the Service Description document
                IGraph svcDescrip = SparqlServiceDescriber.GetServiceDescription(this._config, new Uri(UriFactory.Create(context.Request.Url.AbsoluteUri), this._basePath));
                HandlerHelper.SendToClient(webContext, svcDescrip, this._config);
                return;
            }

            // Check whether we need to use authentication
            if (!HandlerHelper.IsAuthenticated(webContext, this._config.UserGroups, context.Request.HttpMethod))
            {
                return;
            }

            try
            {
                // Invoke the appropriate method on our protocol processor
                switch (context.Request.HttpMethod)
                {
                case "GET":
                    this._config.Processor.ProcessGet(webContext);
                    break;

                case "PUT":
                    this._config.Processor.ProcessPut(webContext);
                    break;

                case "POST":
                    Uri serviceUri = new Uri(UriFactory.Create(context.Request.Url.AbsoluteUri), this._basePath);
                    if (context.Request.Url.AbsoluteUri.Equals(serviceUri.AbsoluteUri))
                    {
                        // If there is a ?graph parameter or ?default parameter then this is a normal Post
                        // Otherwise it is a PostCreate
                        if (context.Request.QueryString["graph"] != null)
                        {
                            this._config.Processor.ProcessPost(webContext);
                        }
                        else if (context.Request.QueryString.AllKeys.Contains("default") || Regex.IsMatch(context.Request.QueryString.ToString(), BaseProtocolProcessor.DefaultParameterPattern))
                        {
                            this._config.Processor.ProcessPost(webContext);
                        }
                        else
                        {
                            this._config.Processor.ProcessPostCreate(webContext);
                        }
                    }
                    else
                    {
                        this._config.Processor.ProcessPost(webContext);
                    }
                    break;

                case "DELETE":
                    this._config.Processor.ProcessDelete(webContext);
                    break;

                case "HEAD":
                    this._config.Processor.ProcessHead(webContext);
                    break;

                case "PATCH":
                    this._config.Processor.ProcessPatch(webContext);
                    break;

                default:
                    // For any other HTTP Verb we send a 405 Method Not Allowed
                    context.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
                    break;
                }

                // Update the Cache as the request may have changed the endpoint
                this.UpdateConfig(context);
            }
            catch (SparqlHttpProtocolUriResolutionException)
            {
                // If URI Resolution fails we send a 400 Bad Request
                context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
            }
            catch (SparqlHttpProtocolUriInvalidException)
            {
                // If URI is invalid we send a 400 Bad Request
                context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
            }
            catch (NotSupportedException)
            {
                // If Not Supported we send a 405 Method Not Allowed
                context.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
            }
            catch (NotImplementedException)
            {
                // If Not Implemented we send a 501 Not Implemented
                context.Response.StatusCode = (int)HttpStatusCode.NotImplemented;
            }
            catch (RdfWriterSelectionException)
            {
                // If we can't select a valid Writer when returning content we send a 406 Not Acceptable
                context.Response.StatusCode = (int)HttpStatusCode.NotAcceptable;
            }
            catch (RdfParserSelectionException)
            {
                // If we can't select a valid Parser when receiving content we send a 415 Unsupported Media Type
                context.Response.StatusCode = (int)HttpStatusCode.UnsupportedMediaType;
            }
            catch (RdfParseException)
            {
                // If we can't parse the received content successfully we send a 400 Bad Request
                context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
            }
            catch (Exception)
            {
                // For any other error we'll send a 500 Internal Server Error
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            }
        }
        /// <summary>
        /// Processes SPARQL Update requests
        /// </summary>
        /// <param name="context">HTTP Context</param>
        public void ProcessRequest(HttpContext context)
        {
            this._config = this.LoadConfig(context);
            WebContext webContext = new WebContext(context);

            // Add our Standard Headers
            HandlerHelper.AddStandardHeaders(webContext, this._config);

            // Options we need to determine based on the HTTP Method used
            String[]      updates;
            String        updateText        = null;
            List <String> userDefaultGraphs = new List <String>();
            List <String> userNamedGraphs   = new List <String>();

            try
            {
                // Decide what to do based on the HTTP Method
                switch (context.Request.HttpMethod.ToUpper())
                {
                case "OPTIONS":
                    // OPTIONS requests always result in the Service Description document
                    IGraph svcDescrip = SparqlServiceDescriber.GetServiceDescription(this._config, UriFactory.Create(context.Request.Url.AbsoluteUri));
                    HandlerHelper.SendToClient(webContext, svcDescrip, this._config);
                    return;

                case "HEAD":
                    // Just return from a HEAD request
                    return;

                case "GET":
                    // A GET with an update parameter is a Bad Request
                    updates = context.Request.QueryString.GetValues("update");
                    if (updates != null && updates.Length > 0)
                    {
                        throw new ArgumentException("Updates cannot be submitted as GET requests");
                    }

                    // Otherwise GET either results in the Service Description if appropriately conneg'd or
                    // the update form if enabled

                    try
                    {
                        // If we might show the Update Form only show the Description if the selected writer is
                        // not a HTML writer
                        MimeTypeDefinition definition = MimeTypesHelper.GetDefinitions(webContext.GetAcceptTypes()).FirstOrDefault(d => d.CanWriteRdf);
                        if (definition != null)
                        {
                            IRdfWriter writer = definition.GetRdfWriter();
                            if (!(writer is IHtmlWriter))
                            {
                                // If not a HTML Writer selected then show the Service Description Graph
                                // unless an error occurs creating it
                                IGraph serviceDescrip = SparqlServiceDescriber.GetServiceDescription(this._config, UriFactory.Create(context.Request.Url.AbsoluteUri));
                                context.Response.ContentType     = definition.CanonicalMimeType;
                                context.Response.ContentEncoding = definition.Encoding;
                                writer.Save(serviceDescrip, new StreamWriter(context.Response.OutputStream, definition.Encoding));
                                return;
                            }
                        }
                    }
                    catch
                    {
                        // Ignore Exceptions - we'll just show the Query Form or return a 400 Bad Request instead
                    }

                    // If a Writer can't be selected then we'll either show the Update Form or return a 400 Bad Request
                    if (this._config.ShowUpdateForm)
                    {
                        this.ShowUpdateForm(context);
                    }
                    else
                    {
                        throw new ArgumentException("Updates cannot be submitted as GET requests");
                    }
                    return;

                case "POST":

                    if (context.Request.ContentType != null)
                    {
                        MimeTypeSelector contentType = MimeTypeSelector.Create(context.Request.ContentType, 0);
                        if (contentType.Type.Equals(MimeTypesHelper.WWWFormURLEncoded))
                        {
                            // Form URL Encoded was declared type so expect an update parameter in the Form parameters
                            updates = context.Request.Form.GetValues("update");
                            if (updates == null)
                            {
                                throw new ArgumentException("Required update parameter in POST body was missing");
                            }
                            if (updates.Length == 0)
                            {
                                throw new ArgumentException("Required update parameter in POST body was missing");
                            }
                            if (updates.Length > 1)
                            {
                                throw new ArgumentException("The update parameter was specified multiple times in the POST body");
                            }
                            updateText = updates[0];

                            // For Form URL Encoded the Using/Using Named Graphs may be specified by Form parameters
                            // Get the USING URIs (if any)
                            if (context.Request.Form["using-graph-uri"] != null)
                            {
                                userDefaultGraphs.AddRange(context.Request.Form.GetValues("using-graph-uri"));
                            }
                            // Get the USING NAMED URIs (if any)
                            if (context.Request.Form["using-named-graph-uri"] != null)
                            {
                                userNamedGraphs.AddRange(context.Request.Form.GetValues("using-named-graph-uri"));
                            }

                            break;
                        }
                        else if (contentType.Type.Equals(MimeTypesHelper.SparqlUpdate))
                        {
                            // application/sparql-update was declared type so expect utf-8 charset (if present)
                            if (contentType.Charset != null && !contentType.Charset.ToLower().Equals(MimeTypesHelper.CharsetUtf8))
                            {
                                throw new ArgumentException("HTTP POST request was received with a " + MimeTypesHelper.SparqlUpdate + " Content-Type but a non UTF-8 charset parameter");
                            }

                            using (StreamReader reader = new StreamReader(context.Request.InputStream))
                            {
                                updateText = reader.ReadToEnd();
                                reader.Close();
                            }

                            // For application/sparql-update the Using/Using Named Graphs may be specified by querystring parameters
                            // Get the USING URIs (if any)
                            if (context.Request.QueryString["using-graph-uri"] != null)
                            {
                                userDefaultGraphs.AddRange(context.Request.QueryString.GetValues("using-graph-uri"));
                            }
                            // Get the USING NAMED URIs (if any)
                            if (context.Request.QueryString["using-named-graph-uri"] != null)
                            {
                                userNamedGraphs.AddRange(context.Request.QueryString.GetValues("using-named-graph-uri"));
                            }

                            break;
                        }
                        else
                        {
                            throw new ArgumentException("HTTP POST made to SPARQL update endpoint had an invalid Content-Type header, only " + MimeTypesHelper.WWWFormURLEncoded + " and " + MimeTypesHelper.SparqlUpdate + " are acceptable");
                        }
                    }
                    throw new ArgumentException("HTTP POST made to SPARQL Query endpoint was missing the required Content-Type header");

                default:
                    throw new NotSupportedException("HTTP " + context.Request.HttpMethod.ToUpper() + " is not supported by a SPARQL Update endpoint");
                }

                // Clean up protocol provided dataset
                userDefaultGraphs.RemoveAll(g => String.IsNullOrEmpty(g));
                userNamedGraphs.RemoveAll(g => String.IsNullOrEmpty(g));

                // Now we're going to parse the Updates
                SparqlUpdateParser parser = new SparqlUpdateParser();
                parser.DefaultBaseUri      = context.Request.Url;
                parser.ExpressionFactories = this._config.ExpressionFactories;
                SparqlUpdateCommandSet commands = parser.ParseFromString(updateText);

                // Check whether we need to use authentication
                // If there are no user groups then no authentication is in use so we default to authenticated with no per-action authentication needed
                bool isAuth = true, requireActionAuth = false;
                if (this._config.UserGroups.Any())
                {
                    // If we have user
                    isAuth            = HandlerHelper.IsAuthenticated(webContext, this._config.UserGroups);
                    requireActionAuth = true;
                }
                if (!isAuth)
                {
                    return;
                }

                // First check actions to see whether they are all permissible and apply USING/USING NAMED parameters
                foreach (SparqlUpdateCommand cmd in commands.Commands)
                {
                    // Authenticate each action
                    bool actionAuth = true;
                    if (requireActionAuth)
                    {
                        actionAuth = HandlerHelper.IsAuthenticated(webContext, this._config.UserGroups, this.GetPermissionAction(cmd));
                    }
                    if (!actionAuth)
                    {
                        throw new SparqlUpdatePermissionException("You are not authorised to perform the " + this.GetPermissionAction(cmd) + " action");
                    }

                    // Check whether we need to (and are permitted to) apply USING/USING NAMED parameters
                    if (userDefaultGraphs.Count > 0 || userNamedGraphs.Count > 0)
                    {
                        BaseModificationCommand modify = cmd as BaseModificationCommand;
                        if (modify != null)
                        {
                            if (modify.GraphUri != null || modify.UsingUris.Any() || modify.UsingNamedUris.Any())
                            {
                                // Invalid if a command already has a WITH/USING/USING NAMED
                                throw new SparqlUpdateMalformedException("A command in your update request contains a WITH/USING/USING NAMED clause but you have also specified one/both of the using-graph-uri or using-named-graph-uri parameters which is not permitted by the SPARQL Protocol");
                            }
                            else
                            {
                                // Otherwise go ahead and apply
                                userDefaultGraphs.ForEach(u => modify.AddUsingUri(UriFactory.Create(u)));
                                userNamedGraphs.ForEach(u => modify.AddUsingNamedUri(UriFactory.Create(u)));
                            }
                        }
                    }
                }

                // Then assuming we got here this means all our actions are permitted so now we can process the updates
                this.ProcessUpdates(commands);

                // Flush outstanding changes
                this._config.Processor.Flush();

                // Update the Cache as the request may have changed the endpoint
                this.UpdateConfig(context);
            }
            catch (RdfParseException parseEx)
            {
                HandleErrors(context, "Parsing Error", updateText, parseEx, (int)HttpStatusCode.BadRequest);
            }
            catch (SparqlUpdatePermissionException permEx)
            {
                HandleErrors(context, "Permissions Error", updateText, permEx, (int)HttpStatusCode.Forbidden);
            }
            catch (SparqlUpdateMalformedException malEx)
            {
                HandleErrors(context, "Malformed Update Error", updateText, malEx, (int)HttpStatusCode.BadRequest);
            }
            catch (SparqlUpdateException updateEx)
            {
                HandleErrors(context, "Update Error", updateText, updateEx);
            }
            catch (RdfException rdfEx)
            {
                HandleErrors(context, "RDF Error", updateText, rdfEx);
            }
            catch (NotSupportedException notSupEx)
            {
                HandleErrors(context, "HTTP Request Error", null, notSupEx, (int)HttpStatusCode.MethodNotAllowed);
            }
            catch (ArgumentException argEx)
            {
                HandleErrors(context, "HTTP Request Error", null, argEx, (int)HttpStatusCode.BadRequest);
            }
            catch (Exception ex)
            {
                HandleErrors(context, "Error", updateText, ex);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Generates a SPARQL Service Description Graph for the specified portion of the SPARQL Server Handler Configuration or uses the configuration supplied Description Graph
        /// </summary>
        /// <param name="context">HTTP Context</param>
        /// <param name="config">SPARQL Server Configuration</param>
        /// <param name="descripUri">Base URI of the Description</param>
        /// <param name="type">Portion of the SPARQL Server to describe</param>
        /// <returns></returns>
        public static IGraph GetServiceDescription(HttpContext context, BaseSparqlServerConfiguration config, Uri descripUri, ServiceDescriptionType type)
        {
            //Use user specified Service Description if present
            if (config.ServiceDescription != null)
            {
                return(config.ServiceDescription);
            }

            IGraph   g       = SparqlServiceDescriber.GetNewGraph();
            IUriNode rdfType = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfType));
            IUriNode service = g.CreateUriNode("sd:" + ClassService);

            INode queryNode, updateNode, protocolNode;

            //Query Service Description
            if (config.QueryProcessor != null && (type == ServiceDescriptionType.Query || type == ServiceDescriptionType.All))
            {
                //Add the Top Level Node representing the Query Service
                queryNode = g.CreateUriNode(new Uri(descripUri, "query"));
                g.Assert(queryNode, rdfType, service);

                //Add its sd:url
                IUriNode url = g.CreateUriNode("sd:" + PropertyUrl);
                g.Assert(queryNode, url, queryNode);

                //Add the sd:supportedLanguage
                IUriNode supportedLang = g.CreateUriNode("sd:" + PropertySupportedLanguage);
                IUriNode lang;
                switch (config.QuerySyntax)
                {
                case SparqlQuerySyntax.Extended:
                case SparqlQuerySyntax.Sparql_1_1:
                    lang = g.CreateUriNode("sd:" + InstanceSparql11Query);
                    break;

                default:
                    lang = g.CreateUriNode("sd:" + InstanceSparql10Query);
                    break;
                }
                g.Assert(queryNode, supportedLang, lang);

                //Add the Result Formats
                IUriNode resultFormat = g.CreateUriNode("sd:" + PropertyResultFormat);
                foreach (MimeTypeDefinition definition in MimeTypesHelper.Definitions)
                {
                    if (definition.CanWriteRdf || definition.CanWriteSparqlResults)
                    {
                        if (definition.FormatUri != null)
                        {
                            g.Assert(queryNode, resultFormat, g.CreateUriNode(new Uri(definition.FormatUri)));
                        }
                    }
                }

                //Add Features and Dataset Description
                //First add descriptions for Global Expression Factories
                IUriNode extensionFunction  = g.CreateUriNode("sd:" + PropertyExtensionFunction);
                IUriNode extensionAggregate = g.CreateUriNode("sd:" + PropertyExtensionAggregate);
                foreach (ISparqlCustomExpressionFactory factory in SparqlExpressionFactory.Factories)
                {
                    foreach (Uri u in factory.AvailableExtensionFunctions)
                    {
                        g.Assert(queryNode, extensionFunction, g.CreateUriNode(u));
                    }
                    foreach (Uri u in factory.AvailableExtensionAggregates)
                    {
                        g.Assert(queryNode, extensionAggregate, g.CreateUriNode(u));
                    }
                }
            }
            else
            {
                queryNode = null;
            }

            //Update Service Description
            if (config.UpdateProcessor != null && (type == ServiceDescriptionType.Update || type == ServiceDescriptionType.All))
            {
                //Add the Top Level Node representing the Update Service
                updateNode = g.CreateUriNode(new Uri(descripUri, "update"));
                g.Assert(updateNode, rdfType, service);

                //Add its sd:url
                IUriNode url = g.CreateUriNode("sd:" + PropertyUrl);
                g.Assert(updateNode, url, updateNode);

                //Add the sd:supportedLanguage
                IUriNode supportedLang = g.CreateUriNode("sd:" + PropertySupportedLanguage);
                g.Assert(updateNode, supportedLang, g.CreateUriNode("sd:" + InstanceSparql11Update));

                //Add Features and Dataset Description
                //First add descriptions for Global Expression Factories
                IUriNode extensionFunction  = g.CreateUriNode("sd:" + PropertyExtensionFunction);
                IUriNode extensionAggregate = g.CreateUriNode("sd:" + PropertyExtensionAggregate);
                foreach (ISparqlCustomExpressionFactory factory in SparqlExpressionFactory.Factories)
                {
                    foreach (Uri u in factory.AvailableExtensionFunctions)
                    {
                        g.Assert(updateNode, extensionFunction, g.CreateUriNode(u));
                    }
                    foreach (Uri u in factory.AvailableExtensionAggregates)
                    {
                        g.Assert(updateNode, extensionAggregate, g.CreateUriNode(u));
                    }
                }
            }
            else
            {
                updateNode = null;
            }

            //Graph Store HTTP Protocol Description
            if (config.ProtocolProcessor != null && (type == ServiceDescriptionType.Protocol || type == ServiceDescriptionType.All))
            {
                //Add the Top Level Node representing the Service
                if (descripUri.ToString().EndsWith("/description"))
                {
                    String actualUri = descripUri.ToString();
                    actualUri    = actualUri.Substring(0, actualUri.LastIndexOf("/description") + 1);
                    protocolNode = g.CreateUriNode(new Uri(actualUri));
                }
                else
                {
                    protocolNode = g.CreateUriNode(descripUri);
                }
                g.Assert(protocolNode, rdfType, service);

                //Add its sd:url
                IUriNode url = g.CreateUriNode("sd:" + PropertyUrl);
                g.Assert(protocolNode, url, protocolNode);

                //Add the Input Formats
                IUriNode inputFormat = g.CreateUriNode("sd:" + PropertyInputFormat);
                foreach (MimeTypeDefinition definition in MimeTypesHelper.Definitions)
                {
                    if (definition.CanParseRdf)
                    {
                        if (definition.FormatUri != null)
                        {
                            g.Assert(protocolNode, inputFormat, g.CreateUriNode(new Uri(definition.FormatUri)));
                        }
                    }
                }

                //Add the Result Formats
                IUriNode resultFormat = g.CreateUriNode("sd:" + PropertyResultFormat);
                foreach (MimeTypeDefinition definition in MimeTypesHelper.Definitions)
                {
                    if (definition.CanWriteRdf)
                    {
                        if (definition.FormatUri != null)
                        {
                            g.Assert(protocolNode, resultFormat, g.CreateUriNode(new Uri(definition.FormatUri)));
                        }
                    }
                }
            }
            else
            {
                protocolNode = null;
            }

            //Finally get the Configuration Node to add additional feature and dataset descriptions
            config.AddFeatureDescription(g, queryNode, updateNode, protocolNode);

            return(g);
        }
Esempio n. 8
0
        /// <summary>
        /// Generates a SPARQL Service Description Graph for the given Query Handler Configuration or uses the configuration supplied Description Graph
        /// </summary>
        /// <param name="context">HTTP Context</param>
        /// <param name="config">Query Handler Configuration</param>
        /// <param name="descripUri">Base URI of the Description</param>
        /// <returns></returns>
        public static IGraph GetServiceDescription(HttpContext context, BaseQueryHandlerConfiguration config, Uri descripUri)
        {
            //Use user specified Service Description if present
            if (config.ServiceDescription != null)
            {
                return(config.ServiceDescription);
            }

            IGraph g = SparqlServiceDescriber.GetNewGraph();

            //Add the Top Level Node representing the Service
            IUriNode descrip = g.CreateUriNode(descripUri);
            IUriNode rdfType = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfType));
            IUriNode service = g.CreateUriNode("sd:" + ClassService);

            g.Assert(descrip, rdfType, service);

            //Add its sd:url
            IUriNode url = g.CreateUriNode("sd:" + PropertyUrl);

            g.Assert(descrip, url, descrip);

            //Add the sd:supportedLanguage - Requires Query Language to be configurable through the Configuration API
            IUriNode supportedLang = g.CreateUriNode("sd:" + PropertySupportedLanguage);
            IUriNode lang;

            switch (config.Syntax)
            {
            case SparqlQuerySyntax.Extended:
            case SparqlQuerySyntax.Sparql_1_1:
                lang = g.CreateUriNode("sd:" + InstanceSparql11Query);
                break;

            default:
                lang = g.CreateUriNode("sd:" + InstanceSparql10Query);
                break;
            }
            g.Assert(descrip, supportedLang, lang);

            //Add the Result Formats
            IUriNode resultFormat = g.CreateUriNode("sd:" + PropertyResultFormat);

            foreach (MimeTypeDefinition definition in MimeTypesHelper.Definitions)
            {
                if (definition.CanWriteRdf || definition.CanWriteSparqlResults)
                {
                    if (definition.FormatUri != null)
                    {
                        g.Assert(descrip, resultFormat, g.CreateUriNode(new Uri(definition.FormatUri)));
                    }
                }
            }

            //Add Features and Dataset Description
            //First add descriptions for Global Expression Factories
            IUriNode extensionFunction  = g.CreateUriNode("sd:" + PropertyExtensionFunction);
            IUriNode extensionAggregate = g.CreateUriNode("sd:" + PropertyExtensionAggregate);

            foreach (ISparqlCustomExpressionFactory factory in SparqlExpressionFactory.Factories)
            {
                foreach (Uri u in factory.AvailableExtensionFunctions)
                {
                    g.Assert(descrip, extensionFunction, g.CreateUriNode(u));
                }
                foreach (Uri u in factory.AvailableExtensionAggregates)
                {
                    g.Assert(descrip, extensionAggregate, g.CreateUriNode(u));
                }
            }

            //Then get the Configuration Object to add any other Feature Descriptions it wishes to
            config.AddFeatureDescription(g, descrip);

            return(g);
        }
Esempio n. 9
0
        /// <summary>
        /// Processes Update requests
        /// </summary>
        /// <param name="context">HTTP Context</param>
        public void ProcessUpdateRequest(HttpContext context)
        {
            if (this._config.UpdateProcessor == null)
            {
                context.Response.StatusCode = (int)HttpStatusCode.NotImplemented;
                return;
            }

            if (context.Request.HttpMethod.Equals("OPTIONS"))
            {
                //OPTIONS requests always result in the Service Description document
                IGraph svcDescrip = SparqlServiceDescriber.GetServiceDescription(context, this._config, new Uri(context.Request.Url.AbsoluteUri), ServiceDescriptionType.Update);
                HandlerHelper.SendToClient(context, svcDescrip, this._config);
                return;
            }

            //See if there has been an update submitted
            String updateText = context.Request.QueryString["update"];

            if (updateText == null || updateText.Equals(String.Empty))
            {
                updateText = context.Request.Form["update"];
            }

            //If no Update sent either show Update Form or give a HTTP 400 response
            if (updateText == null || updateText.Equals(String.Empty))
            {
                if (this._config.ShowUpdateForm)
                {
                    this.ShowUpdateForm(context);
                    return;
                }
                else
                {
                    context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    return;
                }
            }

            try
            {
                //Now we're going to parse the Updates
                SparqlUpdateParser parser = new SparqlUpdateParser();
                parser.ExpressionFactories = this._config.ExpressionFactories;
                SparqlUpdateCommandSet commands = parser.ParseFromString(updateText);

                //Check whether we need to use authentication
                //If there are no user groups then no authentication is in use so we default to authenticated with no per-action authentication needed
                bool isAuth = true, requireActionAuth = false;
                if (this._config.UserGroups.Any())
                {
                    //If we have user
                    isAuth            = HandlerHelper.IsAuthenticated(context, this._config.UserGroups);
                    requireActionAuth = true;
                }
                if (!isAuth)
                {
                    return;
                }

                //First check actions to see whether they are all permissible
                foreach (SparqlUpdateCommand cmd in commands.Commands)
                {
                    //Authenticate each action
                    bool actionAuth = true;
                    if (requireActionAuth)
                    {
                        actionAuth = HandlerHelper.IsAuthenticated(context, this._config.UserGroups, this.GetUpdatePermissionAction(cmd));
                    }
                    if (!actionAuth)
                    {
                        throw new SparqlUpdateException("You are not authorised to perform the " + this.GetUpdatePermissionAction(cmd) + " action");
                    }
                }

                //Then assuming we got here this means all our actions are permitted so now we can process the updates
                this.ProcessUpdates(commands);

                //Flush outstanding changes
                this._config.UpdateProcessor.Flush();

                //Update the Cache as the request may have changed the endpoint
                this.UpdateConfig(context);
            }
            catch (RdfParseException parseEx)
            {
                HandleUpdateErrors(context, "Parsing Error", updateText, parseEx);
            }
            catch (SparqlUpdateException updateEx)
            {
                HandleUpdateErrors(context, "Update Error", updateText, updateEx);
            }
            catch (RdfException rdfEx)
            {
                HandleUpdateErrors(context, "RDF Error", updateText, rdfEx);
            }
            catch (Exception ex)
            {
                HandleUpdateErrors(context, "Error", updateText, ex);
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Processes Query requests
        /// </summary>
        /// <param name="context">HTTP Context</param>
        public void ProcessQueryRequest(HttpContext context)
        {
            if (this._config.QueryProcessor == null)
            {
                context.Response.StatusCode = (int)HttpStatusCode.NotImplemented;
                return;
            }

            if (context.Request.HttpMethod.Equals("OPTIONS"))
            {
                //OPTIONS requests always result in the Service Description document
                IGraph svcDescrip = SparqlServiceDescriber.GetServiceDescription(context, this._config, new Uri(context.Request.Url.AbsoluteUri), ServiceDescriptionType.Query);
                HandlerHelper.SendToClient(context, svcDescrip, this._config);
                return;
            }

            //See if there has been an query submitted
            String queryText = context.Request.QueryString["query"];

            if (queryText == null || queryText.Equals(String.Empty))
            {
                queryText = context.Request.Form["query"];
            }

            //If no Query sent either show Query Form or give a HTTP 400 response
            if (queryText == null || queryText.Equals(String.Empty))
            {
                if (this._config.ShowQueryForm)
                {
                    this.ShowQueryForm(context);
                    return;
                }
                else
                {
                    context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    return;
                }
            }

            //Get Other options associated with this query
            List <String> userDefaultGraphs = new List <String>();
            List <String> userNamedGraphs   = new List <String>();
            long          timeout           = 0;
            bool          partialResults    = this._config.DefaultPartialResults;

            //Get the Default Graph URIs (if any)
            if (context.Request.QueryString["default-graph-uri"] != null)
            {
                userDefaultGraphs.AddRange(context.Request.QueryString.GetValues("default-graph-uri"));
            }
            else if (context.Request.Form["default-graph-uri"] != null)
            {
                userDefaultGraphs.AddRange(context.Request.Form.GetValues("default-graph-uri"));
            }
            //Get the Named Graph URIs (if any)
            if (context.Request.QueryString["named-graph-uri"] != null)
            {
                userNamedGraphs.AddRange(context.Request.QueryString.GetValues("named-graph-uri"));
            }
            else if (context.Request.Form["named-graph-uri"] != null)
            {
                userNamedGraphs.AddRange(context.Request.Form.GetValues("named-graph-uri"));
            }

            //Get Timeout setting (if any)
            if (context.Request.QueryString["timeout"] != null)
            {
                if (!Int64.TryParse(context.Request.QueryString["timeout"], out timeout))
                {
                    timeout = this._config.DefaultTimeout;
                }
            }
            else if (context.Request.Form["timeout"] != null)
            {
                if (!Int64.TryParse(context.Request.Form["timeout"], out timeout))
                {
                    timeout = this._config.DefaultTimeout;
                }
            }
            //Get Partial Results Setting (if any);
            if (context.Request.QueryString["partialResults"] != null)
            {
                if (!Boolean.TryParse(context.Request.QueryString["partialResults"], out partialResults))
                {
                    partialResults = this._config.DefaultPartialResults;
                }
            }
            else if (context.Request.Form["partialResults"] != null)
            {
                if (!Boolean.TryParse(context.Request.Form["partialResults"], out partialResults))
                {
                    partialResults = this._config.DefaultPartialResults;
                }
            }

            try
            {
                //Now we're going to parse the Query
                SparqlQueryParser parser = new SparqlQueryParser(this._config.QuerySyntax);
                parser.ExpressionFactories = this._config.ExpressionFactories;
                parser.QueryOptimiser      = this._config.QueryOptimiser;
                SparqlQuery query = parser.ParseFromString(queryText);
                query.AlgebraOptimisers = this._config.AlgebraOptimisers;

                //Check whether we need to use authentication
                //If there are no user groups then no authentication is in use so we default to authenticated with no per-action authentication needed
                bool isAuth = true, requireActionAuth = false;
                if (this._config.UserGroups.Any())
                {
                    //If we have user
                    isAuth            = HandlerHelper.IsAuthenticated(context, this._config.UserGroups);
                    requireActionAuth = true;
                }
                if (!isAuth)
                {
                    return;
                }

                //Is this user allowed to make this kind of query?
                if (requireActionAuth)
                {
                    HandlerHelper.IsAuthenticated(context, this._config.UserGroups, this.GetQueryPermissionAction(query));
                }

                //Set the Default Graph URIs (if any)
                if (userDefaultGraphs.Count > 0)
                {
                    //Default Graph Uri specified by default-graph-uri parameter or Web.config settings
                    foreach (String userDefaultGraph in userDefaultGraphs)
                    {
                        if (!userDefaultGraph.Equals(String.Empty))
                        {
                            query.AddDefaultGraph(new Uri(userDefaultGraph));
                        }
                    }
                }
                else if (!this._config.DefaultGraphURI.Equals(String.Empty))
                {
                    //Only applies if the Query doesn't specify any Default Graph
                    if (!query.DefaultGraphs.Any())
                    {
                        query.AddDefaultGraph(new Uri(this._config.DefaultGraphURI));
                    }
                }

                //Set the Named Graph URIs (if any)
                if (userNamedGraphs.Count > 0)
                {
                    foreach (String userNamedGraph in userNamedGraphs)
                    {
                        if (!userNamedGraph.Equals(String.Empty))
                        {
                            query.AddNamedGraph(new Uri(userNamedGraph));
                        }
                    }
                }

                //Set Timeout setting
                if (timeout > 0)
                {
                    query.Timeout = timeout;
                }
                else
                {
                    query.Timeout = this._config.DefaultTimeout;
                }

                //Set Partial Results Setting
                query.PartialResultsOnTimeout = partialResults;

                //Set Describe Algorithm
                query.Describer = this._config.DescribeAlgorithm;

                //Now we can finally make the query and return the results
                Object result = this.ProcessQuery(query);
                this.ProcessQueryResults(context, result);

                //Update the Cache as the request may have changed the endpoint
                this.UpdateConfig(context);
            }
            catch (RdfParseException parseEx)
            {
                HandleQueryErrors(context, "Parsing Error", queryText, parseEx, (int)HttpStatusCode.BadRequest);
            }
            catch (RdfQueryTimeoutException timeoutEx)
            {
                HandleQueryErrors(context, "Query Timeout Error", queryText, timeoutEx);
            }
            catch (RdfQueryException queryEx)
            {
                HandleQueryErrors(context, "Query Error", queryText, queryEx);
            }
            catch (RdfWriterSelectionException writerSelEx)
            {
                HandleQueryErrors(context, "Output Selection Error", queryText, writerSelEx, (int)HttpStatusCode.NotAcceptable);
            }
            catch (RdfException rdfEx)
            {
                HandleQueryErrors(context, "RDF Error", queryText, rdfEx);
            }
            catch (Exception ex)
            {
                HandleQueryErrors(context, "Error", queryText, ex);
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Processes SPARQL Update requests
        /// </summary>
        /// <param name="context">HTTP Context</param>
        public void ProcessRequest(HttpContext context)
        {
            this._config = this.LoadConfig(context);

            //Add our Standard Headers
            HandlerHelper.AddStandardHeaders(context, this._config);

            if (context.Request.HttpMethod.Equals("OPTIONS"))
            {
                //OPTIONS requests always result in the Service Description document
                IGraph svcDescrip = SparqlServiceDescriber.GetServiceDescription(context, this._config, new Uri(context.Request.Url.AbsoluteUri));
                HandlerHelper.SendToClient(context, svcDescrip, this._config);
                return;
            }

            //See if there has been an update submitted
            String updateText = context.Request.QueryString["update"];

            if (updateText == null || updateText.Equals(String.Empty))
            {
                updateText = context.Request.Form["update"];
            }

            //If no Update sent either show Update Form or give a HTTP 400 response
            if (updateText == null || updateText.Equals(String.Empty))
            {
                //If there is no Update we may return the SPARQL Service Description where appropriate
                try
                {
                    //If we might show the Update Form only show the Description if the selected writer is
                    //not a HTML writer
                    MimeTypeDefinition definition = MimeTypesHelper.GetDefinitions(HandlerHelper.GetAcceptTypes(context)).FirstOrDefault(d => d.CanWriteRdf);
                    if (definition != null)
                    {
                        IRdfWriter writer = definition.GetRdfWriter();
                        if (!this._config.ShowUpdateForm || !(writer is IHtmlWriter))
                        {
                            //If not a HTML Writer selected OR not showing Update Form then show the Service Description Graph
                            //unless an error occurs creating it
                            IGraph serviceDescrip = SparqlServiceDescriber.GetServiceDescription(context, this._config, new Uri(context.Request.Url.AbsoluteUri));
                            context.Response.ContentType     = definition.CanonicalMimeType;
                            context.Response.ContentEncoding = definition.Encoding;
                            writer.Save(serviceDescrip, new StreamWriter(context.Response.OutputStream, definition.Encoding));
                            return;
                        }
                    }
                }
                catch
                {
                    //Ignore Exceptions - we'll just show the Query Form or return a 400 Bad Request instead
                }

                //If a Writer can't be selected then we'll either show the Update Form or return a 400 Bad Request
                if (this._config.ShowUpdateForm)
                {
                    this.ShowUpdateForm(context);
                }
                else
                {
                    context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                }
                return;
            }

            try
            {
                //Now we're going to parse the Updates
                SparqlUpdateParser parser = new SparqlUpdateParser();
                parser.ExpressionFactories = this._config.ExpressionFactories;
                SparqlUpdateCommandSet commands = parser.ParseFromString(updateText);

                //Check whether we need to use authentication
                //If there are no user groups then no authentication is in use so we default to authenticated with no per-action authentication needed
                bool isAuth = true, requireActionAuth = false;
                if (this._config.UserGroups.Any())
                {
                    //If we have user
                    isAuth            = HandlerHelper.IsAuthenticated(context, this._config.UserGroups);
                    requireActionAuth = true;
                }
                if (!isAuth)
                {
                    return;
                }

                //First check actions to see whether they are all permissible
                foreach (SparqlUpdateCommand cmd in commands.Commands)
                {
                    //Authenticate each action
                    bool actionAuth = true;
                    if (requireActionAuth)
                    {
                        actionAuth = HandlerHelper.IsAuthenticated(context, this._config.UserGroups, this.GetPermissionAction(cmd));
                    }
                    if (!actionAuth)
                    {
                        throw new SparqlUpdateException("You are not authorised to perform the " + this.GetPermissionAction(cmd) + " action");
                    }
                }

                //Then assuming we got here this means all our actions are permitted so now we can process the updates
                this.ProcessUpdates(commands);

                //Flush outstanding changes
                this._config.Processor.Flush();

                //Update the Cache as the request may have changed the endpoint
                this.UpdateConfig(context);
            }
            catch (RdfParseException parseEx)
            {
                HandleErrors(context, "Parsing Error", updateText, parseEx);
            }
            catch (SparqlUpdateException updateEx)
            {
                HandleErrors(context, "Update Error", updateText, updateEx);
            }
            catch (RdfException rdfEx)
            {
                HandleErrors(context, "RDF Error", updateText, rdfEx);
            }
            catch (Exception ex)
            {
                HandleErrors(context, "Error", updateText, ex);
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Processes SPARQL Update requests
        /// </summary>
        /// <param name="context">HTTP Context</param>
        public void ProcessRequest(HttpContext context)
        {
            this._config = this.LoadConfig(context);

            //Add our Standard Headers
            HandlerHelper.AddStandardHeaders(context, this._config);

            if (context.Request.HttpMethod.Equals("OPTIONS"))
            {
                //OPTIONS requests always result in the Service Description document
                IGraph svcDescrip = SparqlServiceDescriber.GetServiceDescription(context, this._config, UriFactory.Create(context.Request.Url.AbsoluteUri));
                HandlerHelper.SendToClient(context, svcDescrip, this._config);
                return;
            }

            //See if there has been an update submitted
            String updateText = null;

            if (context.Request.ContentType != null)
            {
                if (context.Request.ContentType.Equals(MimeTypesHelper.WWWFormURLEncoded))
                {
                    updateText = context.Request.Form["update"];
                }
                else if (context.Request.ContentType.Equals(MimeTypesHelper.SparqlUpdate))
                {
                    updateText = new StreamReader(context.Request.InputStream).ReadToEnd();
                }
            }
            else
            {
                updateText = context.Request.Form["update"];
            }

            //If no Update sent either show Update Form or give a HTTP 400 response
            if (updateText == null || updateText.Equals(String.Empty))
            {
                //If there is no Update we may return the SPARQL Service Description where appropriate
                try
                {
                    //If we might show the Update Form only show the Description if the selected writer is
                    //not a HTML writer
                    MimeTypeDefinition definition = MimeTypesHelper.GetDefinitions(HandlerHelper.GetAcceptTypes(context)).FirstOrDefault(d => d.CanWriteRdf);
                    if (definition != null)
                    {
                        IRdfWriter writer = definition.GetRdfWriter();
                        if (!this._config.ShowUpdateForm || !(writer is IHtmlWriter))
                        {
                            //If not a HTML Writer selected OR not showing Update Form then show the Service Description Graph
                            //unless an error occurs creating it
                            IGraph serviceDescrip = SparqlServiceDescriber.GetServiceDescription(context, this._config, UriFactory.Create(context.Request.Url.AbsoluteUri));
                            context.Response.ContentType     = definition.CanonicalMimeType;
                            context.Response.ContentEncoding = definition.Encoding;
                            writer.Save(serviceDescrip, new StreamWriter(context.Response.OutputStream, definition.Encoding));
                            return;
                        }
                    }
                }
                catch
                {
                    //Ignore Exceptions - we'll just show the Query Form or return a 400 Bad Request instead
                }

                //If a Writer can't be selected then we'll either show the Update Form or return a 400 Bad Request
                if (this._config.ShowUpdateForm)
                {
                    this.ShowUpdateForm(context);
                }
                else
                {
                    context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                }
                return;
            }

            //Get Other options associated with this update
            List <String> userDefaultGraphs = new List <String>();
            List <String> userNamedGraphs   = new List <String>();

            //Get the USING URIs (if any)
            if (context.Request.QueryString["using-graph-uri"] != null)
            {
                userDefaultGraphs.AddRange(context.Request.QueryString.GetValues("using-graph-uri"));
            }
            else if (context.Request.Form["using-graph-uri"] != null)
            {
                userDefaultGraphs.AddRange(context.Request.Form.GetValues("using-graph-uri"));
            }
            //Get the USING NAMED URIs (if any)
            if (context.Request.QueryString["using-named-graph-uri"] != null)
            {
                userNamedGraphs.AddRange(context.Request.QueryString.GetValues("using-named-graph-uri"));
            }
            else if (context.Request.Form["using-named-graph-uri"] != null)
            {
                userNamedGraphs.AddRange(context.Request.Form.GetValues("using-named-graph-uri"));
            }

            try
            {
                //Now we're going to parse the Updates
                SparqlUpdateParser parser = new SparqlUpdateParser();
                parser.ExpressionFactories = this._config.ExpressionFactories;
                SparqlUpdateCommandSet commands = parser.ParseFromString(updateText);

                //Check whether we need to use authentication
                //If there are no user groups then no authentication is in use so we default to authenticated with no per-action authentication needed
                bool isAuth = true, requireActionAuth = false;
                if (this._config.UserGroups.Any())
                {
                    //If we have user
                    isAuth            = HandlerHelper.IsAuthenticated(context, this._config.UserGroups);
                    requireActionAuth = true;
                }
                if (!isAuth)
                {
                    return;
                }

                //First check actions to see whether they are all permissible and apply USING/USING NAMED parameters
                foreach (SparqlUpdateCommand cmd in commands.Commands)
                {
                    //Authenticate each action
                    bool actionAuth = true;
                    if (requireActionAuth)
                    {
                        actionAuth = HandlerHelper.IsAuthenticated(context, this._config.UserGroups, this.GetPermissionAction(cmd));
                    }
                    if (!actionAuth)
                    {
                        throw new SparqlUpdatePermissionException("You are not authorised to perform the " + this.GetPermissionAction(cmd) + " action");
                    }

                    //Check whether we need to (and are permitted to) apply USING/USING NAMED parameters
                    if (userDefaultGraphs.Count > 0 || userNamedGraphs.Count > 0)
                    {
                        BaseModificationCommand modify = cmd as BaseModificationCommand;
                        if (modify != null)
                        {
                            if (modify.GraphUri != null || modify.UsingUris.Any() || modify.UsingNamedUris.Any())
                            {
                                //Invalid if a command already has a WITH/USING/USING NAMED
                                throw new SparqlUpdateMalformedException("A command in your update request contains a WITH/USING/USING NAMED clause but you have also specified one/both of the using-graph-uri or using-named-graph-uri parameters which is not permitted by the SPARQL Protocol");
                            }
                            else
                            {
                                //Otherwise go ahead and apply
                                userDefaultGraphs.ForEach(u => modify.AddUsingUri(UriFactory.Create(u)));
                                userNamedGraphs.ForEach(u => modify.AddUsingNamedUri(UriFactory.Create(u)));
                            }
                        }
                    }
                }

                //Then assuming we got here this means all our actions are permitted so now we can process the updates
                this.ProcessUpdates(commands);

                //Flush outstanding changes
                this._config.Processor.Flush();

                //Update the Cache as the request may have changed the endpoint
                this.UpdateConfig(context);
            }
            catch (RdfParseException parseEx)
            {
                HandleErrors(context, "Parsing Error", updateText, parseEx, (int)HttpStatusCode.BadRequest);
            }
            catch (SparqlUpdatePermissionException permEx)
            {
                HandleErrors(context, "Permissions Error", updateText, permEx, (int)HttpStatusCode.Forbidden);
            }
            catch (SparqlUpdateMalformedException malEx)
            {
                HandleErrors(context, "Malformed Update Error", updateText, malEx, (int)HttpStatusCode.BadRequest);
            }
            catch (SparqlUpdateException updateEx)
            {
                HandleErrors(context, "Update Error", updateText, updateEx);
            }
            catch (RdfException rdfEx)
            {
                HandleErrors(context, "RDF Error", updateText, rdfEx);
            }
            catch (Exception ex)
            {
                HandleErrors(context, "Error", updateText, ex);
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Processes a SPARQL Query Request
        /// </summary>
        /// <param name="context">HTTP Context</param>
        public void ProcessRequest(HttpContext context)
        {
            this._config = this.LoadConfig(context);

            //Add our Standard Headers
            HandlerHelper.AddStandardHeaders(context, this._config);

            if (context.Request.HttpMethod.Equals("OPTIONS"))
            {
                //OPTIONS requests always result in the Service Description document
                IGraph svcDescrip = SparqlServiceDescriber.GetServiceDescription(context, this._config, new Uri(context.Request.Url.AbsoluteUri));
                HandlerHelper.SendToClient(context, svcDescrip, this._config);
                return;
            }

            //See if there has been an query submitted
            String queryText = context.Request.QueryString["query"];

            if (queryText == null || queryText.Equals(String.Empty))
            {
                queryText = context.Request.Form["query"];
            }

            //If no Query sent either show Query Form or give a HTTP 400 response
            if (queryText == null || queryText.Equals(String.Empty))
            {
                //If there is no Query we may return the SPARQL Service Description where appropriate
                try
                {
                    //If we might show the Query Form only show the Description if the selected writer is
                    //not a HTML writer
                    MimeTypeDefinition definition = MimeTypesHelper.GetDefinitions(HandlerHelper.GetAcceptTypes(context)).FirstOrDefault(d => d.CanWriteRdf);
                    if (definition != null)
                    {
                        IRdfWriter writer = definition.GetRdfWriter();
                        if (!this._config.ShowQueryForm || !(writer is IHtmlWriter))
                        {
                            //If not a HTML Writer selected OR not showing Query Form then show the Service Description Graph
                            //unless an error occurs creating it
                            IGraph serviceDescrip = SparqlServiceDescriber.GetServiceDescription(context, this._config, new Uri(context.Request.Url.AbsoluteUri));
                            context.Response.ContentType     = definition.CanonicalMimeType;
                            context.Response.ContentEncoding = definition.Encoding;
                            writer.Save(serviceDescrip, new StreamWriter(context.Response.OutputStream, definition.Encoding));
                            return;
                        }
                    }
                }
                catch
                {
                    //Ignore Exceptions - we'll just show the Query Form or return a 400 Bad Request instead
                }

                //If a Writer can't be selected then we'll either show the Query Form or return a 400 Bad Request
                if (this._config.ShowQueryForm)
                {
                    this.ShowQueryForm(context);
                }
                else
                {
                    context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                }
                return;
            }

            //Get Other options associated with this query
            List <String> userDefaultGraphs = new List <String>();
            List <String> userNamedGraphs   = new List <String>();
            long          timeout           = 0;
            bool          partialResults    = this._config.DefaultPartialResults;

            //Get the Default Graph URIs (if any)
            if (context.Request.QueryString["default-graph-uri"] != null)
            {
                userDefaultGraphs.AddRange(context.Request.QueryString.GetValues("default-graph-uri"));
            }
            else if (context.Request.Form["default-graph-uri"] != null)
            {
                userDefaultGraphs.AddRange(context.Request.Form.GetValues("default-graph-uri"));
            }
            //Get the Named Graph URIs (if any)
            if (context.Request.QueryString["named-graph-uri"] != null)
            {
                userNamedGraphs.AddRange(context.Request.QueryString.GetValues("named-graph-uri"));
            }
            else if (context.Request.Form["named-graph-uri"] != null)
            {
                userNamedGraphs.AddRange(context.Request.Form.GetValues("named-graph-uri"));
            }

            //Get Timeout setting (if any)
            if (context.Request.QueryString["timeout"] != null)
            {
                if (!Int64.TryParse(context.Request.QueryString["timeout"], out timeout))
                {
                    timeout = this._config.DefaultTimeout;
                }
            }
            else if (context.Request.Form["timeout"] != null)
            {
                if (!Int64.TryParse(context.Request.Form["timeout"], out timeout))
                {
                    timeout = this._config.DefaultTimeout;
                }
            }
            //Get Partial Results Setting (if any);
            if (context.Request.QueryString["partialResults"] != null)
            {
                if (!Boolean.TryParse(context.Request.QueryString["partialResults"], out partialResults))
                {
                    partialResults = this._config.DefaultPartialResults;
                }
            }
            else if (context.Request.Form["partialResults"] != null)
            {
                if (!Boolean.TryParse(context.Request.Form["partialResults"], out partialResults))
                {
                    partialResults = this._config.DefaultPartialResults;
                }
            }

            try
            {
                //Now we're going to parse the Query
                SparqlQueryParser parser = new SparqlQueryParser(this._config.Syntax);
                parser.ExpressionFactories = this._config.ExpressionFactories;
                parser.QueryOptimiser      = this._config.QueryOptimiser;
                SparqlQuery query = parser.ParseFromString(queryText);
                query.AlgebraOptimisers = this._config.AlgebraOptimisers;

                //Check whether we need to use authentication
                //If there are no user groups then no authentication is in use so we default to authenticated with no per-action authentication needed
                bool isAuth = true, requireActionAuth = false;
                if (this._config.UserGroups.Any())
                {
                    //If we have user
                    isAuth            = HandlerHelper.IsAuthenticated(context, this._config.UserGroups);
                    requireActionAuth = true;
                }
                if (!isAuth)
                {
                    return;
                }

                //Is this user allowed to make this kind of query?
                if (requireActionAuth)
                {
                    HandlerHelper.IsAuthenticated(context, this._config.UserGroups, this.GetPermissionAction(query));
                }

                //Set the Default Graph URIs (if any)
                if (userDefaultGraphs.Count > 0)
                {
                    //Default Graph Uri specified by default-graph-uri parameter or Web.config settings
                    foreach (String userDefaultGraph in userDefaultGraphs)
                    {
                        if (!userDefaultGraph.Equals(String.Empty))
                        {
                            query.AddDefaultGraph(new Uri(userDefaultGraph));
                        }
                    }
                }
                else if (!this._config.DefaultGraphURI.Equals(String.Empty))
                {
                    //Only applies if the Query doesn't specify any Default Graph
                    if (!query.DefaultGraphs.Any())
                    {
                        query.AddDefaultGraph(new Uri(this._config.DefaultGraphURI));
                    }
                }

                //Set the Named Graph URIs (if any)
                if (userNamedGraphs.Count > 0)
                {
                    foreach (String userNamedGraph in userNamedGraphs)
                    {
                        if (!userNamedGraph.Equals(String.Empty))
                        {
                            query.AddNamedGraph(new Uri(userNamedGraph));
                        }
                    }
                }

                //Set Timeout setting
                if (timeout > 0)
                {
                    query.Timeout = timeout;
                }
                else
                {
                    query.Timeout = this._config.DefaultTimeout;
                }

                //Set Partial Results Setting
                query.PartialResultsOnTimeout = partialResults;

                //Set Describe Algorithm
                query.Describer = this._config.DescribeAlgorithm;

                //Now we can finally make the query and return the results
                Object result = this.ProcessQuery(query);
                this.ProcessResults(context, result);

                //Update the Cache as the request may have changed the endpoint
                this.UpdateConfig(context);
            }
            catch (RdfParseException parseEx)
            {
                HandleErrors(context, "Parsing Error", queryText, parseEx, (int)HttpStatusCode.BadRequest);
            }
            catch (RdfQueryTimeoutException timeoutEx)
            {
                HandleErrors(context, "Query Timeout Error", queryText, timeoutEx);
            }
            catch (RdfQueryException queryEx)
            {
                HandleErrors(context, "Update Error", queryText, queryEx);
            }
            catch (RdfWriterSelectionException writerSelEx)
            {
                HandleErrors(context, "Output Selection Error", queryText, writerSelEx, (int)HttpStatusCode.NotAcceptable);
            }
            catch (RdfException rdfEx)
            {
                HandleErrors(context, "RDF Error", queryText, rdfEx);
            }
            catch (Exception ex)
            {
                HandleErrors(context, "Error", queryText, ex);
            }
        }
Esempio n. 14
0
        /// <summary>
        /// Processes a SPARQL Query Request
        /// </summary>
        /// <param name="context">HTTP Context</param>
        public void ProcessRequest(HttpContext context)
        {
            this._config = this.LoadConfig(context);
            WebContext webContext = new WebContext(context);

            //Add our Standard Headers
            HandlerHelper.AddStandardHeaders(webContext, this._config);

            //Options we need to determine based on the HTTP Method used
            String[]      queries;
            String        queryText         = null;
            List <String> userDefaultGraphs = new List <String>();
            List <String> userNamedGraphs   = new List <String>();

            try
            {
                //Decide what to do based on the HTTP Method
                switch (context.Request.HttpMethod.ToUpper())
                {
                case "OPTIONS":
                    //OPTIONS requests always result in the Service Description document
                    IGraph svcDescrip = SparqlServiceDescriber.GetServiceDescription(this._config, UriFactory.Create(context.Request.Url.AbsoluteUri));
                    HandlerHelper.SendToClient(webContext, svcDescrip, this._config);
                    return;

                case "HEAD":
                    //Just return from a HEAD request
                    return;

                case "GET":
                    //GET expects a query parameter in the querystring
                    queries = context.Request.QueryString.GetValues("query");
                    if (queries != null)
                    {
                        if (queries.Length > 1)
                        {
                            throw new ArgumentException("The query parameter was specified multiple times in the querystring");
                        }
                        queryText = queries.Length == 1 ? queries[0] : null;
                    }

                    //If no Query sent either show Query Form or give a HTTP 400 response
                    if (String.IsNullOrEmpty(queryText))
                    {
                        //If there is no Query we may return the SPARQL Service Description where appropriate
                        try
                        {
                            //If we might show the Query Form only show the Description if the selected writer is
                            //not a HTML writer
                            MimeTypeDefinition definition = MimeTypesHelper.GetDefinitions(HandlerHelper.GetAcceptTypes(webContext)).FirstOrDefault(d => d.CanWriteRdf);
                            if (definition != null)
                            {
                                IRdfWriter writer = definition.GetRdfWriter();
                                if (!this._config.ShowQueryForm || !(writer is IHtmlWriter))
                                {
                                    //If not a HTML Writer selected OR not showing Query Form then show the Service Description Graph
                                    //unless an error occurs creating it
                                    IGraph serviceDescrip = SparqlServiceDescriber.GetServiceDescription(this._config, UriFactory.Create(context.Request.Url.AbsoluteUri));
                                    context.Response.ContentType     = definition.CanonicalMimeType;
                                    context.Response.ContentEncoding = definition.Encoding;
                                    writer.Save(serviceDescrip, new StreamWriter(context.Response.OutputStream, definition.Encoding));
                                    return;
                                }
                            }
                        }
                        catch
                        {
                            //Ignore Exceptions - we'll just show the Query Form or return a 400 Bad Request instead
                        }

                        //Otherwise we'll either show the Query Form or return a 400 Bad Request
                        if (this._config.ShowQueryForm)
                        {
                            this.ShowQueryForm(context);
                        }
                        else
                        {
                            throw new ArgumentException("Missing required query parameter");
                        }
                        return;
                    }

                    //Get the Default Graph URIs (if any)
                    if (context.Request.QueryString["default-graph-uri"] != null)
                    {
                        userDefaultGraphs.AddRange(context.Request.QueryString.GetValues("default-graph-uri"));
                    }
                    //Get the Named Graph URIs (if any)
                    if (context.Request.QueryString["named-graph-uri"] != null)
                    {
                        userNamedGraphs.AddRange(context.Request.QueryString.GetValues("named-graph-uri"));
                    }
                    break;

                case "POST":
                    //POST requires a valid content type
                    if (context.Request.ContentType != null)
                    {
                        MimeTypeSelector contentType = MimeTypeSelector.Create(context.Request.ContentType, 0);
                        if (contentType.Type.Equals(MimeTypesHelper.WWWFormURLEncoded))
                        {
                            //Form URL Encoded was declared type so expect a query parameter in the Form parameters
                            queries = context.Request.Form.GetValues("query");
                            if (queries == null)
                            {
                                throw new ArgumentException("Required query parameter in POST body was missing");
                            }
                            if (queries.Length == 0)
                            {
                                throw new ArgumentException("Required query parameter in POST body was missing");
                            }
                            if (queries.Length > 1)
                            {
                                throw new ArgumentException("The query parameter was specified multiple times in the POST body");
                            }
                            queryText = queries[0];

                            //For Form URL Encoded the Default/Named Graphs may be specified by Form parameters
                            //Get the Default Graph URIs (if any)
                            if (context.Request.Form["default-graph-uri"] != null)
                            {
                                userDefaultGraphs.AddRange(context.Request.Form.GetValues("default-graph-uri"));
                            }
                            //Get the Named Graph URIs (if any)
                            if (context.Request.Form["named-graph-uri"] != null)
                            {
                                userNamedGraphs.AddRange(context.Request.Form.GetValues("named-graph-uri"));
                            }

                            break;
                        }
                        else if (contentType.Type.Equals(MimeTypesHelper.SparqlQuery))
                        {
                            //application/sparql-query was declared type so expect utf-8 charset (if present)
                            if (contentType.Charset != null && !contentType.Charset.ToLower().Equals(MimeTypesHelper.CharsetUtf8))
                            {
                                throw new ArgumentException("HTTP POST request was received with a " + MimeTypesHelper.SparqlQuery + " Content-Type but a non UTF-8 charset parameter");
                            }

                            //Read the query from the request body
                            using (StreamReader reader = new StreamReader(context.Request.InputStream))
                            {
                                queryText = reader.ReadToEnd();
                                reader.Close();
                            }

                            //For application/sparql-query the Default/Named Graphs may be specified by querystring parameters
                            //Get the Default Graph URIs (if any)
                            if (context.Request.QueryString["default-graph-uri"] != null)
                            {
                                userDefaultGraphs.AddRange(context.Request.QueryString.GetValues("default-graph-uri"));
                            }
                            //Get the Named Graph URIs (if any)
                            if (context.Request.QueryString["named-graph-uri"] != null)
                            {
                                userNamedGraphs.AddRange(context.Request.QueryString.GetValues("named-graph-uri"));
                            }

                            break;
                        }
                        else
                        {
                            throw new ArgumentException("HTTP POST made to SPARQL query endpoint had an invalid Content-Type header, only " + MimeTypesHelper.WWWFormURLEncoded + " and " + MimeTypesHelper.SparqlQuery + " are acceptable");
                        }
                    }
                    throw new ArgumentException("HTTP POST made to SPARQL Query endpoint was missing the required Content-Type header");

                default:
                    throw new NotSupportedException("HTTP " + context.Request.HttpMethod.ToUpper() + " is not supported by a SPARQL Query endpoint");
                }

                //Get non-standard options associated with the query
                long timeout        = 0;
                bool partialResults = this._config.DefaultPartialResults;

                //Get Timeout setting (if any)
                if (context.Request.QueryString["timeout"] != null)
                {
                    if (!Int64.TryParse(context.Request.QueryString["timeout"], out timeout))
                    {
                        timeout = this._config.DefaultTimeout;
                    }
                }
                else if (context.Request.Form["timeout"] != null)
                {
                    if (!Int64.TryParse(context.Request.Form["timeout"], out timeout))
                    {
                        timeout = this._config.DefaultTimeout;
                    }
                }
                //Get Partial Results Setting (if any);
                if (context.Request.QueryString["partialResults"] != null)
                {
                    if (!Boolean.TryParse(context.Request.QueryString["partialResults"], out partialResults))
                    {
                        partialResults = this._config.DefaultPartialResults;
                    }
                }
                else if (context.Request.Form["partialResults"] != null)
                {
                    if (!Boolean.TryParse(context.Request.Form["partialResults"], out partialResults))
                    {
                        partialResults = this._config.DefaultPartialResults;
                    }
                }

                //Now we're going to parse the Query
                SparqlQueryParser parser = new SparqlQueryParser(this._config.Syntax);
                parser.DefaultBaseUri      = context.Request.Url;
                parser.ExpressionFactories = this._config.ExpressionFactories;
                parser.QueryOptimiser      = this._config.QueryOptimiser;
                SparqlQuery query = parser.ParseFromString(queryText);
                query.AlgebraOptimisers         = this._config.AlgebraOptimisers;
                query.PropertyFunctionFactories = this._config.PropertyFunctionFactories;

                //Check whether we need to use authentication
                //If there are no user groups then no authentication is in use so we default to authenticated with no per-action authentication needed
                bool isAuth = true, requireActionAuth = false;
                if (this._config.UserGroups.Any())
                {
                    //If we have user
                    isAuth            = HandlerHelper.IsAuthenticated(webContext, this._config.UserGroups);
                    requireActionAuth = true;
                }
                if (!isAuth)
                {
                    return;
                }

                //Is this user allowed to make this kind of query?
                if (requireActionAuth)
                {
                    HandlerHelper.IsAuthenticated(webContext, this._config.UserGroups, this.GetPermissionAction(query));
                }

                //Clear query dataset if there is a protocol defined one
                userDefaultGraphs.RemoveAll(g => String.IsNullOrEmpty(g));
                userNamedGraphs.RemoveAll(g => String.IsNullOrEmpty(g));
                bool isProtocolDataset = false;
                if (userDefaultGraphs.Count > 0 || userNamedGraphs.Count > 0)
                {
                    query.ClearDefaultGraphs();
                    query.ClearNamedGraphs();
                    isProtocolDataset = true;
                }

                //Set the Default Graph URIs (if any)
                if (isProtocolDataset)
                {
                    foreach (String userDefaultGraph in userDefaultGraphs)
                    {
                        query.AddDefaultGraph(UriFactory.Create(userDefaultGraph));
                    }
                }
                else if (!this._config.DefaultGraphURI.Equals(String.Empty))
                {
                    //Only applies if the Query doesn't specify any Default Graph and there wasn't a protocol defined
                    //dataset present
                    if (!query.DefaultGraphs.Any())
                    {
                        query.AddDefaultGraph(UriFactory.Create(this._config.DefaultGraphURI));
                    }
                }

                //Set the Named Graph URIs (if any)
                if (isProtocolDataset)
                {
                    query.ClearNamedGraphs();
                    foreach (String userNamedGraph in userNamedGraphs)
                    {
                        query.AddNamedGraph(UriFactory.Create(userNamedGraph));
                    }
                }

                //Set Timeout setting
                if (timeout > 0)
                {
                    query.Timeout = timeout;
                }
                else
                {
                    query.Timeout = this._config.DefaultTimeout;
                }

                //Set Partial Results Setting
                query.PartialResultsOnTimeout = partialResults;

                //Set Describe Algorithm
                query.Describer = this._config.DescribeAlgorithm;

                //Now we can finally make the query and return the results
                Object result = this.ProcessQuery(query);
                this.ProcessResults(context, result);

                //Update the Cache as the request may have changed the endpoint
                this.UpdateConfig(context);
            }
            catch (RdfParseException parseEx)
            {
                HandleErrors(context, "Parsing Error", queryText, parseEx, (int)HttpStatusCode.BadRequest);
            }
            catch (RdfQueryTimeoutException timeoutEx)
            {
                HandleErrors(context, "Query Timeout Error", queryText, timeoutEx);
            }
            catch (RdfQueryException queryEx)
            {
                HandleErrors(context, "Update Error", queryText, queryEx);
            }
            catch (RdfWriterSelectionException writerSelEx)
            {
                HandleErrors(context, "Output Selection Error", queryText, writerSelEx, (int)HttpStatusCode.NotAcceptable);
            }
            catch (RdfException rdfEx)
            {
                HandleErrors(context, "RDF Error", queryText, rdfEx);
            }
            catch (NotSupportedException notSupEx)
            {
                HandleErrors(context, "HTTP Request Error", null, notSupEx, (int)HttpStatusCode.MethodNotAllowed);
            }
            catch (ArgumentException argEx)
            {
                HandleErrors(context, "HTTP Request Error", null, argEx, (int)HttpStatusCode.BadRequest);
            }
            catch (Exception ex)
            {
                HandleErrors(context, "Error", queryText, ex);
            }
        }