public void TestLangSpecParsing(String file) { this.EnsureTestData(file); MimeTypeDefinition def = MimeTypesHelper.GetDefinitions(MimeTypesHelper.GetMimeTypes(Path.GetExtension(file))).FirstOrDefault(); if (def != null) { if (def.CanParseRdf) { Graph g = new Graph(); g.LoadFromFile(file); Assert.AreEqual(this._original, g); } else if (def.CanParseRdfDatasets) { TripleStore store = new TripleStore(); store.LoadFromFile(file); Assert.AreEqual(this._original, store.Graphs.First()); } } else { Assert.Fail("Unsupported file type"); } }
private void EnsureTestData(String file) { if (this._original == null) { Graph g = new Graph(); g.Assert(g.CreateBlankNode(), g.CreateUriNode(UriFactory.Create("http://example.org/predicate")), g.CreateLiteralNode("literal", "en-123")); g.Assert(g.CreateBlankNode(), g.CreateUriNode(UriFactory.Create("http://example.org/predicate")), g.CreateLiteralNode("literal", "en-gb-us")); g.Assert(g.CreateBlankNode(), g.CreateUriNode(UriFactory.Create("http://example.org/predicate")), g.CreateLiteralNode("literal", "en-123-abc")); this._original = g; this._store = new TripleStore(); this._store.Add(this._original); } if (!File.Exists(file)) { MimeTypeDefinition def = MimeTypesHelper.GetDefinitions(MimeTypesHelper.GetMimeTypes(Path.GetExtension(file))).FirstOrDefault(); Assert.NotNull(def); if (def != null) { Assert.True(def.CanWriteRdf || def.CanWriteRdfDatasets, "Unable to ensure test data"); if (def.CanWriteRdf) { this._original.SaveToFile(file); } else if (def.CanWriteRdfDatasets) { this._store.SaveToFile(file); } } } Assert.True(File.Exists(file), "Unable to ensure test data:" + Path.GetFullPath(file)); }
public void ParsingObjectsUpdateTypeCheck() { Type target = typeof(SparqlUpdateParser); MimeTypeDefinition def = MimeTypesHelper.Definitions.FirstOrDefault(d => d.CanParseObject <SparqlUpdateCommandSet>()); Assert.AreNotEqual(null, def, "Should get a valid definition"); Assert.AreEqual(target, def.GetObjectParserType <SparqlUpdateCommandSet>()); }
public void ParsingObjectsUpdateTypeCheck() { Type target = typeof(SparqlUpdateParser); MimeTypeDefinition def = MimeTypesHelper.Definitions.FirstOrDefault(d => d.CanParseObject <SparqlUpdateCommandSet>()); Assert.NotNull(def); Assert.Equal(target, def.GetObjectParserType <SparqlUpdateCommandSet>()); }
/// <summary> /// Internal Helper method which does the actual loading of the Triple Store from the Resource /// </summary> /// <param name="handler">RDF Handler to use</param> /// <param name="asm">Assembly to get the resource stream from</param> /// <param name="resource">Full name of the Resource (without the Assembly Name)</param> /// <param name="parser">Parser to use (if null will be auto-selected)</param> private static void LoadDatasetInternal(IRdfHandler handler, Assembly asm, String resource, IStoreReader parser) { //Resource is in the given assembly using (Stream s = asm.GetManifestResourceStream(resource)) { if (s == null) { //Resource did not exist in this assembly throw new RdfParseException("The Embedded Resource '" + resource + "' does not exist inside of " + GetAssemblyName(asm)); } else { //Resource exists //Do we have a predefined Parser? if (parser != null) { parser.Load(handler, new StreamReader(s)); } else { //Need to select a Parser or use StringParser String ext = MimeTypesHelper.GetTrueResourceExtension(resource); MimeTypeDefinition def = MimeTypesHelper.GetDefinitionsByFileExtension(ext).FirstOrDefault(d => d.CanParseRdfDatasets); if (def != null) { //Resource has an appropriate file extension and we've found a candidate parser for it parser = def.GetRdfDatasetParser(); parser.Load(handler, new StreamReader(s)); } else { //See if the format was actually an RDF graph instead def = MimeTypesHelper.GetDefinitionsByFileExtension(ext).FirstOrDefault(d => d.CanParseRdf); if (def != null) { IRdfReader rdfParser = def.GetRdfParser(); rdfParser.Load(handler, new StreamReader(s)); } else { //Resource did not have a file extension or we didn't have a parser associated with the extension //Try using StringParser instead String data; using (StreamReader reader = new StreamReader(s)) { data = reader.ReadToEnd(); #if !PORTABLE reader.Close(); #endif } parser = StringParser.GetDatasetParser(data); parser.Load(handler, new StringReader(data)); } } } } } }
/// <summary> /// Overrides writer Selection to use the <see cref="HtmlSchemaWriter">HtmlSchemaWriter</see> whenever the <see cref="HtmlWriter">HtmlWriter</see> would normally have been used /// </summary> /// <param name="definition">MIME Type Definition selected based on the Requests Accept header</param> /// <returns></returns> protected override IRdfWriter SelectWriter(MimeTypeDefinition definition) { if (_htmlWriter.Equals(definition.RdfWriterType)) { return new HtmlSchemaWriter(); } else { return base.SelectWriter(definition); } }
/// <summary> /// Overrides writer Selection to use the <see cref="HtmlSchemaWriter">HtmlSchemaWriter</see> whenever the <see cref="HtmlWriter">HtmlWriter</see> would normally have been used /// </summary> /// <param name="definition">MIME Type Definition selected based on the Requests Accept header</param> /// <returns></returns> protected override IRdfWriter SelectWriter(MimeTypeDefinition definition) { if (_htmlWriter.Equals(definition.RdfWriterType)) { return(new HtmlSchemaWriter()); } else { return(base.SelectWriter(definition)); } }
/// <summary> /// Requests that the document auto-detect its syntax /// </summary> public void AutoDetectSyntax() { if (this._filename != null && !this._filename.Equals(String.Empty)) { try { //Try filename based syntax detection MimeTypeDefinition def = MimeTypesHelper.GetDefinitionsByFileExtension(MimeTypesHelper.GetTrueFileExtension(this._filename)).FirstOrDefault(); if (def != null) { this.Syntax = def.SyntaxName.GetSyntaxName(); return; } } catch (RdfParserSelectionException) { //Ignore and use string based detection instead } } //Otherwise try and use string based detection //First take a guess at it being a SPARQL Results format String text = this.Text; try { ISparqlResultsReader resultsReader = StringParser.GetResultSetParser(text); this.Syntax = resultsReader.GetSyntaxName(); } catch (RdfParserSelectionException) { //Then see whether it may be a SPARQL query if (text.Contains("SELECT") || text.Contains("CONSTRUCT") || text.Contains("DESCRIBE") || text.Contains("ASK")) { //Likely a SPARQL Query this.Syntax = "SparqlQuery11"; } else { //Then take a guess at it being a RDF format try { IRdfReader rdfReader = StringParser.GetParser(text); this.Syntax = rdfReader.GetSyntaxName(); } catch (RdfParserSelectionException) { //Finally take a guess at it being a RDF Dataset format IStoreReader datasetReader = StringParser.GetDatasetParser(text); this.Syntax = datasetReader.GetSyntaxName(); } } } }
/// <summary> /// Creates a new connection to a Fuseki Server. /// </summary> /// <param name="serviceUri">The /data URI of the Fuseki Server.</param> /// <param name="writerMimeTypeDefinition">The MIME type of the syntax to use when sending RDF data to the server. Defaults to RDF/XML.</param> public FusekiConnector(String serviceUri, MimeTypeDefinition writerMimeTypeDefinition = null) : base(serviceUri, writerMimeTypeDefinition) { if (!serviceUri.ToString().EndsWith("/data")) { throw new ArgumentException("This does not appear to be a valid Fuseki Server URI, you must provide the URI that ends with /data", "serviceUri"); } _updateUri = serviceUri.Substring(0, serviceUri.Length - 4) + "update"; _queryUri = serviceUri.Substring(0, serviceUri.Length - 4) + "query"; }
public void ParsingObjectsQueryParserCheck() { Type target = typeof(SparqlQueryParser); MimeTypeDefinition def = MimeTypesHelper.Definitions.FirstOrDefault(d => d.CanParseObject <SparqlQuery>()); Assert.AreNotEqual(null, def, "Should get a valid definition"); Assert.AreEqual(target, def.GetObjectParserType <SparqlQuery>()); IObjectParser <SparqlQuery> parser = def.GetObjectParser <SparqlQuery>(); SparqlQuery q = parser.ParseFromString("SELECT * WHERE { ?s ?p ?o }"); Console.WriteLine(q.ToString()); }
public void ParsingObjectsUpdateParserCheck() { Type target = typeof(SparqlUpdateParser); MimeTypeDefinition def = MimeTypesHelper.Definitions.FirstOrDefault(d => d.CanParseObject <SparqlUpdateCommandSet>()); Assert.AreNotEqual(null, def, "Should get a valid definition"); Assert.AreEqual(target, def.GetObjectParserType <SparqlUpdateCommandSet>()); IObjectParser <SparqlUpdateCommandSet> parser = def.GetObjectParser <SparqlUpdateCommandSet>(); SparqlUpdateCommandSet cmds = parser.ParseFromString("CLEAR DEFAULT"); Console.WriteLine(cmds.ToString()); }
/// <summary> /// Internal Helper method which does the actual loading of the Graph from the Resource /// </summary> /// <param name="handler">RDF Handler to use</param> /// <param name="asm">Assembly to get the resource stream from</param> /// <param name="resource">Full name of the Resource (without the Assembly Name)</param> /// <param name="parser">Parser to use (if null then will be auto-selected)</param> private static void LoadGraphInternal(IRdfHandler handler, Assembly asm, String resource, IRdfReader parser) { //Resource is in the given assembly using (Stream s = asm.GetManifestResourceStream(resource)) { if (s == null) { //Resource did not exist in this assembly throw new RdfParseException("The Embedded Resource '" + resource + "' does not exist inside of " + asm.GetName().Name); } else { //Resource exists //Did we get a defined parser to use? if (parser != null) { parser.Load(handler, new StreamReader(s)); } else { //Need to select a Parser or use StringParser String ext = resource.Substring(resource.LastIndexOf(".")); MimeTypeDefinition def = MimeTypesHelper.GetDefinitions(MimeTypesHelper.GetMimeTypes(ext)).FirstOrDefault(d => d.CanParseRdf); if (def != null) { //Resource has an appropriate file extension and we've found a candidate parser for it parser = def.GetRdfParser(); parser.Load(handler, new StreamReader(s)); } else { //Resource did not have a file extension or we didn't have a parser associated with the extension //Try using StringParser instead String data; using (StreamReader reader = new StreamReader(s)) { data = reader.ReadToEnd(); reader.Close(); } parser = StringParser.GetParser(data); parser.Load(handler, new StringReader(data)); } } } } }
public void ParsingGZipByFilenameAuto1() { foreach (String filename in this._autoTestFiles) { Graph g = new Graph(); String ext = MimeTypesHelper.GetTrueFileExtension(filename); ext = ext.Substring(1); MimeTypeDefinition def = MimeTypesHelper.Definitions.Where(d => d.CanParseRdf && d.SupportsFileExtension(ext)).FirstOrDefault(); Assert.NotNull(def); IRdfReader reader = def.GetRdfParser(); reader.Load(g, filename); Assert.Equal(this._g, g); } }
/// <summary> /// Creates a new SPARQL Graph Store HTTP Protocol Connector /// </summary> /// <param name="serviceUri">URI of the Protocol Server</param> /// <param name="writerMimeTypeDefinition">The MIME type specifying the syntax to use when sending RDF data to the server. Defaults to "application/rdf+xml"</param> public SparqlHttpProtocolConnector(string serviceUri, MimeTypeDefinition writerMimeTypeDefinition = null) { if (serviceUri == null) { throw new ArgumentNullException(nameof(serviceUri), "Cannot create a connection to a Graph Store HTTP Protocol store if the Service URI is null"); } if (serviceUri.Equals(string.Empty)) { throw new ArgumentException( "Cannot create a connection to a Graph Store HTTP Protocol store if the Service URI is null/empty", nameof(serviceUri)); } _writerMimeTypeDefinition = writerMimeTypeDefinition ?? MimeTypesHelper.GetDefinitions("application/rdf+xml").First(); _serviceUri = serviceUri; }
public void ParsingGZipDatasetByGZipStreamManual() { foreach (String filename in this._manualDatasetTestFiles) { TripleStore store = new TripleStore(); String ext = MimeTypesHelper.GetTrueFileExtension(filename); ext = ext.Substring(1); MimeTypeDefinition def = MimeTypesHelper.Definitions.Where(d => d.CanParseRdfDatasets && d.SupportsFileExtension(ext)).FirstOrDefault(); Assert.NotNull(def); IStoreReader reader = def.GetRdfDatasetParser(); reader.Load(store, new StreamReader(new GZipStream(new FileStream(filename, FileMode.Open, FileAccess.Read), CompressionMode.Decompress))); Assert.Equal(this._g, store.Graphs.First()); } }
public void ParsingGZipByGZipStreamAuto() { foreach (String filename in this._autoTestFiles) { Graph g = new Graph(); String ext = MimeTypesHelper.GetTrueFileExtension(filename); ext = ext.Substring(1); MimeTypeDefinition def = MimeTypesHelper.Definitions.Where(d => d.CanParseRdf && d.SupportsFileExtension(ext)).FirstOrDefault(); Assert.NotNull(def); IRdfReader reader = def.GetRdfParser(); reader.Load(g, new StreamReader(new GZipStream(new FileStream(filename, FileMode.Open, FileAccess.Read), CompressionMode.Decompress))); Assert.Equal(this._g, g); } }
public void ParsingGZipResultsByStreamManual() { foreach (String filename in this._manualResultsTestFiles) { SparqlResultSet results = new SparqlResultSet(); String ext = MimeTypesHelper.GetTrueFileExtension(filename); ext = ext.Substring(1); MimeTypeDefinition def = MimeTypesHelper.Definitions.Where(d => d.CanParseSparqlResults && d.SupportsFileExtension(ext)).FirstOrDefault(); Assert.NotNull(def); ISparqlResultsReader reader = def.GetSparqlResultsParser(); reader.Load(results, File.OpenText(filename)); Assert.True(this._results.Equals(results), "Result Sets for file " + filename + " were not equal"); } }
public void ParsingGZipResultsByGZipStreamAuto() { foreach (String filename in this._autoResultsTestFiles) { SparqlResultSet results = new SparqlResultSet(); String ext = MimeTypesHelper.GetTrueFileExtension(filename); ext = ext.Substring(1); MimeTypeDefinition def = MimeTypesHelper.Definitions.Where(d => d.CanParseSparqlResults && d.SupportsFileExtension(ext)).FirstOrDefault(); Assert.NotNull(def); ISparqlResultsReader reader = def.GetSparqlResultsParser(); reader.Load(results, new StreamReader(new GZipStream(new FileStream(filename, FileMode.Open, FileAccess.Read), CompressionMode.Decompress))); Assert.True(this._results.Equals(results), "Result Sets for file " + filename + " were not equal"); } }
public void ParsingGZipByStreamAuto() { foreach (String filename in this._autoTestFiles) { Graph g = new Graph(); String ext = MimeTypesHelper.GetTrueFileExtension(filename); ext = ext.Substring(1); MimeTypeDefinition def = MimeTypesHelper.Definitions.Where(d => d.CanParseRdf && d.SupportsFileExtension(ext)).FirstOrDefault(); if (def == null) { Assert.Fail("Failed to find MIME Type Definition for File Extension ." + ext); } IRdfReader reader = def.GetRdfParser(); reader.Load(g, new StreamReader(filename)); Assert.AreEqual(this._g, g, "Graphs for file " + filename + " were not equal"); } }
public void ParsingGZipResultsByGZipStreamManual() { foreach (String filename in this._manualResultsTestFiles) { SparqlResultSet results = new SparqlResultSet(); String ext = MimeTypesHelper.GetTrueFileExtension(filename); ext = ext.Substring(1); MimeTypeDefinition def = MimeTypesHelper.Definitions.Where(d => d.CanParseSparqlResults && d.SupportsFileExtension(ext)).FirstOrDefault(); if (def == null) { Assert.Fail("Failed to find MIME Type Definition for File Extension ." + ext); } ISparqlResultsReader reader = def.GetSparqlResultsParser(); reader.Load(results, new StreamReader(new GZipStream(new FileStream(filename, FileMode.Open, FileAccess.Read), CompressionMode.Decompress))); Assert.AreEqual(this._results, results, "Result Sets for file " + filename + " were not equal"); } }
public void ParsingGZipDatasetByGZipStreamAuto() { foreach (String filename in this._autoDatasetTestFiles) { TripleStore store = new TripleStore(); String ext = MimeTypesHelper.GetTrueFileExtension(filename); ext = ext.Substring(1); MimeTypeDefinition def = MimeTypesHelper.Definitions.Where(d => d.CanParseRdfDatasets && d.SupportsFileExtension(ext)).FirstOrDefault(); if (def == null) { Assert.Fail("Failed to find MIME Type Definition for File Extension ." + ext); } IStoreReader reader = def.GetRdfDatasetParser(); reader.Load(store, new StreamReader(new GZipStream(new FileStream(filename, FileMode.Open, FileAccess.Read), CompressionMode.Decompress))); Assert.AreEqual(this._g, store.Graphs.First(), "Graphs for file " + filename + " were not equal"); } }
public void ParsingGZipResultsByStreamAuto() { foreach (String filename in this._autoResultsTestFiles) { SparqlResultSet results = new SparqlResultSet(); String ext = MimeTypesHelper.GetTrueFileExtension(filename); ext = ext.Substring(1); MimeTypeDefinition def = MimeTypesHelper.Definitions.Where(d => d.CanParseSparqlResults && d.SupportsFileExtension(ext)).FirstOrDefault(); if (def == null) { Assert.Fail("Failed to find MIME Type Definition for File Extension ." + ext); } ISparqlResultsReader reader = def.GetSparqlResultsParser(); reader.Load(results, new StreamReader(filename)); Assert.IsTrue(this._results.Equals(results), "Result Sets for file " + filename + " were not equal"); } }
/// <summary> /// Sends the given Graph to the Client via the HTTP Response. /// </summary> /// <param name="context">HTTP Context.</param> /// <param name="g">Graph to send.</param> protected void SendResultsToClient(IHttpContext context, IGraph g) { IRdfWriter writer; String ctype; // Look up the MIME Type Definition - if none use GetWriter instead MimeTypeDefinition definition = MimeTypesHelper.GetDefinitions(context.GetAcceptTypes()).FirstOrDefault(d => d.CanWriteRdf); if (definition != null) { writer = definition.GetRdfWriter(); ctype = definition.CanonicalMimeType; } else { writer = MimeTypesHelper.GetWriter(context.GetAcceptTypes(), out ctype); } // Set up the Writer if (writer is ICompressingWriter) { ((ICompressingWriter)writer).CompressionLevel = Options.DefaultCompressionLevel; } // Send Content to Client context.Response.ContentType = ctype; if (definition != null) { context.Response.ContentEncoding = definition.Encoding; writer.Save(g, new StreamWriter(context.Response.OutputStream, definition.Encoding)); } else { writer.Save(g, new StreamWriter(context.Response.OutputStream)); } }
/// <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); } }
/// <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); } }
public void RunConvert(String[] args) { //Set the Options if (!this.SetOptions(args)) { //If SetOptions returns false then some options were invalid and errors have been output to the error stream return; } //First grab the MIME Type Definitions for the conversion List <MimeTypeDefinition> defs = MimeTypesHelper.GetDefinitions(this._outFormats).ToList(); //Process each input to determine the Conversion Handler to use foreach (IConversionInput input in this._inputs) { String outFile; String ext = this._outExt; //First determine the writer we'll use MimeTypeDefinition graphDef = defs.FirstOrDefault(d => d.CanWriteRdf); if (graphDef != null) { //Then generate the output filename if (ext.Equals(String.Empty)) { ext = "." + graphDef.CanonicalFileExtension; } if (this._inputs.Count == 1 && !this._outputFilename.Equals(String.Empty)) { outFile = this._outputFilename; } else { outFile = input.GetFilename(this._outputFilename, ext); } //Check it doesn't already exist or overwrite is enabled if (File.Exists(outFile) && !this._overwrite) { Console.Error.WriteLine("rdfConvert: Warning: Skipping Conversion of Input " + input.ToString() + " as this would generate the Output File '" + outFile + "' which already exists and the -overwrite option was not specified"); continue; } //Get the Writer and apply Conversion Options IRdfWriter writer = graphDef.GetRdfWriter(); foreach (IConversionOption option in this._options) { option.Apply(writer); } //If -best always use SaveOnCompletionHandler if (this._best) { if (this._verbose) { Console.WriteLine("rdfConvert: Using Best Quality data conversion subject to user specified compression options"); } input.ConversionHandler = new SaveOnCompletionHandler(writer, new StreamWriter(outFile, false, graphDef.Encoding)); } else { //Use the fast WriteThroughHandler where possible if (writer is IFormatterBasedWriter) { if (this._verbose) { Console.WriteLine("rdfConvert: Using Streaming Conversion with formatter " + ((IFormatterBasedWriter)writer).TripleFormatterType.Name); } input.ConversionHandler = new WriteToFileHandler(outFile, graphDef.Encoding, ((IFormatterBasedWriter)writer).TripleFormatterType); } else { //Can't use it in this case if (this._verbose) { Console.WriteLine("rdfConvert: Warning: Target Format not suitable for streaming conversion, input data will be loaded into memory prior to conversion"); } input.ConversionHandler = new SaveOnCompletionHandler(writer, new StreamWriter(outFile, false, graphDef.Encoding)); } } } else { MimeTypeDefinition storeDef = defs.FirstOrDefault(d => d.CanWriteRdfDatasets); if (storeDef != null) { //Then generate the output filename if (ext.Equals(String.Empty)) { ext = "." + storeDef.CanonicalFileExtension; } outFile = input.GetFilename(this._outputFilename, ext); //Get the Writer and apply conversion options IStoreWriter writer = storeDef.GetRdfDatasetWriter(); foreach (IConversionOption option in this._options) { option.Apply(writer); } //If -best always use SaveOnCompletionHandler if (this._best) { if (this._verbose) { Console.WriteLine("rdfConvert: Using Best Quality data conversion subject to user specified compression options"); } input.ConversionHandler = new SaveStoreOnCompletionHandler(writer, new StreamWriter(outFile, false, storeDef.Encoding)); } else { //Use the fast WriteThroughHandler where possible if (writer is IFormatterBasedWriter) { if (this._verbose) { Console.WriteLine("rdfConvert: Using Streaming Conversion with formatter " + ((IFormatterBasedWriter)writer).TripleFormatterType.Name); } input.ConversionHandler = new WriteToFileHandler(outFile, graphDef.Encoding, ((IFormatterBasedWriter)writer).TripleFormatterType); } else { if (this._verbose) { Console.WriteLine("rdfConvert: Warning: Target Format not suitable for streaming conversion, input data will be loaded into memory prior to conversion"); } input.ConversionHandler = new SaveStoreOnCompletionHandler(writer, new StreamWriter(outFile, false, storeDef.Encoding)); } } } else { Console.Error.WriteLine("rdfConvert: Warning: Skipping Conversion of Input " + input.ToString() + " as unable to determine how to convert it"); continue; } } //Then do the Conversion Console.WriteLine("rdfConvert: Converting Input " + input.ToString() + " to '" + outFile + "'..."); try { if (this._verbose) { input.ConversionHandler = new ConversionProgressHandler(input.ConversionHandler); Console.WriteLine("rdfConvert: Debug: Conversion Handler is " + input.ConversionHandler.GetType().FullName); } input.Convert(); Console.WriteLine("rdfConvert: Converted Input " + input.ToString() + " to '" + outFile + "' OK"); } catch (RdfParseException parseEx) { Console.Error.WriteLine("rdfConvert: Error: Error Converting Input " + input.ToString() + " due to a RDF Parse Exception"); Console.Error.WriteLine(parseEx.Message); if (this._debug) { this.DebugErrors(parseEx); } } catch (RdfException rdfEx) { Console.Error.WriteLine("rdfConvert: Error: Error Converting Input " + input.ToString() + " due to a RDF Exception"); Console.Error.WriteLine(rdfEx.Message); if (this._debug) { this.DebugErrors(rdfEx); } } catch (Exception ex) { Console.Error.WriteLine("rdfConvert: Error: Error Converting Input " + input.ToString() + " due to a Unexpected Exception"); Console.Error.WriteLine(ex.Message); if (this._debug) { this.DebugErrors(ex); } } } }
/// <summary> /// Helper function which returns the Results (Graph/Triple Store/SPARQL Results) back to the Client in one of their accepted formats /// </summary> /// <param name="context">Context of the HTTP Request</param> /// <param name="result">Results of the Sparql Query</param> /// <param name="config">Handler Configuration</param> public static void SendToClient(HttpContext context, Object result, BaseHandlerConfiguration config) { MimeTypeDefinition definition = null; String ctype = "text/plain"; String[] acceptTypes = HandlerHelper.GetAcceptTypes(context); //Return the Results if (result is SparqlResultSet) { ISparqlResultsWriter sparqlwriter = null; //Try and get a MIME Type Definition using the HTTP Requests Accept Header if (acceptTypes != null) { definition = MimeTypesHelper.GetDefinitions(acceptTypes).FirstOrDefault(d => d.CanWriteSparqlResults); } //Try and get the registered Definition for SPARQL Results XML if (definition == null) { definition = MimeTypesHelper.GetDefinitions(MimeTypesHelper.SparqlXml[0]).FirstOrDefault(); } //If Definition is still null create a temporary definition if (definition == null) { definition = new MimeTypeDefinition("SPARQL Results XML", MimeTypesHelper.SparqlXml, Enumerable.Empty<String>()); definition.SparqlResultsWriterType = typeof(VDS.RDF.Writing.SparqlXmlWriter); } //Set up the Writer appropriately sparqlwriter = definition.GetSparqlResultsWriter(); context.Response.ContentType = definition.CanonicalMimeType; HandlerHelper.ApplyWriterOptions(sparqlwriter, config); //Clear any existing Response context.Response.Clear(); //Send Result Set to Client context.Response.ContentEncoding = definition.Encoding; sparqlwriter.Save((SparqlResultSet)result, new StreamWriter(context.Response.OutputStream, definition.Encoding)); } else if (result is IGraph) { IRdfWriter rdfwriter = null; //Try and get a MIME Type Definition using the HTTP Requests Accept Header if (acceptTypes != null) { definition = MimeTypesHelper.GetDefinitions(acceptTypes).FirstOrDefault(d => d.CanWriteRdf); } if (definition == null) { //If no appropriate definition then use the GetWriter method instead rdfwriter = MimeTypesHelper.GetWriter(acceptTypes, out ctype); } else { rdfwriter = definition.GetRdfWriter(); } //Setup the writer if (definition != null) ctype = definition.CanonicalMimeType; context.Response.ContentType = ctype; HandlerHelper.ApplyWriterOptions(rdfwriter, config); //Clear any existing Response context.Response.Clear(); //Send Graph to Client if (definition != null) { context.Response.ContentEncoding = definition.Encoding; rdfwriter.Save((IGraph)result, new StreamWriter(context.Response.OutputStream, definition.Encoding)); } else { rdfwriter.Save((IGraph)result, new StreamWriter(context.Response.OutputStream)); } } else if (result is ITripleStore) { IStoreWriter storewriter = null; //Try and get a MIME Type Definition using the HTTP Requests Accept Header if (acceptTypes != null) { definition = MimeTypesHelper.GetDefinitions(acceptTypes).FirstOrDefault(d => d.CanWriteRdfDatasets); storewriter = definition.GetRdfDatasetWriter(); } if (definition == null) { //If no appropriate definition then use the GetStoreWriter method instead storewriter = MimeTypesHelper.GetStoreWriter(acceptTypes, out ctype); } //Setup the writer if (definition != null) ctype = definition.CanonicalMimeType; context.Response.ContentType = ctype; HandlerHelper.ApplyWriterOptions(storewriter, config); //Clear any existing Response context.Response.Clear(); //Send Triple Store to Client if (definition != null) { context.Response.ContentEncoding = definition.Encoding; storewriter.Save((ITripleStore)result, new VDS.RDF.Storage.Params.StreamParams(context.Response.OutputStream, definition.Encoding)); } else { storewriter.Save((ITripleStore)result, new VDS.RDF.Storage.Params.StreamParams(context.Response.OutputStream)); } } else if (result is ISparqlDataset) { //Wrap in a Triple Store and then call self so the Triple Store writing branch of this if gets called instead TripleStore store = new TripleStore(new DatasetGraphCollection((ISparqlDataset)result)); HandlerHelper.SendToClient(context, store, config); } else { throw new RdfOutputException("Unexpected Result Object of Type '" + result.GetType().ToString() + "' returned - unable to write Objects of this Type to the HTTP Response"); } }
/// <summary> /// Helper function which returns the Results (Graph/Triple Store/SPARQL Results) back to the Client in one of their accepted formats /// </summary> /// <param name="context">Context of the HTTP Request</param> /// <param name="result">Results of the Sparql Query</param> /// <param name="config">Handler Configuration</param> public static void SendToClient(HttpContext context, Object result, BaseHandlerConfiguration config) { MimeTypeDefinition definition = null; String ctype = "text/plain"; String[] acceptTypes = HandlerHelper.GetAcceptTypes(context); //Return the Results if (result is SparqlResultSet) { ISparqlResultsWriter sparqlWriter = null; //Try and get a MIME Type Definition using the HTTP Requests Accept Header if (acceptTypes != null) { definition = MimeTypesHelper.GetDefinitions(acceptTypes).FirstOrDefault(d => d.CanWriteSparqlResults); } //Try and get the registered Definition for SPARQL Results XML if (definition == null) { definition = MimeTypesHelper.GetDefinitions(MimeTypesHelper.SparqlXml[0]).FirstOrDefault(); } //If Definition is still null create a temporary definition if (definition == null) { definition = new MimeTypeDefinition("SPARQL Results XML", MimeTypesHelper.SparqlXml, Enumerable.Empty <String>()); definition.SparqlResultsWriterType = typeof(VDS.RDF.Writing.SparqlXmlWriter); } //Set up the Writer appropriately sparqlWriter = definition.GetSparqlResultsWriter(); context.Response.ContentType = definition.CanonicalMimeType; HandlerHelper.ApplyWriterOptions(sparqlWriter, config); //Clear any existing Response context.Response.Clear(); //Send Result Set to Client context.Response.ContentEncoding = definition.Encoding; sparqlWriter.Save((SparqlResultSet)result, new StreamWriter(context.Response.OutputStream, definition.Encoding)); } else if (result is IGraph) { IRdfWriter rdfWriter = null; //Try and get a MIME Type Definition using the HTTP Requests Accept Header if (acceptTypes != null) { definition = MimeTypesHelper.GetDefinitions(acceptTypes).FirstOrDefault(d => d.CanWriteRdf); } if (definition == null) { //If no appropriate definition then use the GetWriter method instead rdfWriter = MimeTypesHelper.GetWriter(acceptTypes, out ctype); } else { rdfWriter = definition.GetRdfWriter(); } //Setup the writer if (definition != null) { ctype = definition.CanonicalMimeType; } context.Response.ContentType = ctype; HandlerHelper.ApplyWriterOptions(rdfWriter, config); //Clear any existing Response context.Response.Clear(); //Send Graph to Client if (definition != null) { context.Response.ContentEncoding = definition.Encoding; rdfWriter.Save((IGraph)result, new StreamWriter(context.Response.OutputStream, definition.Encoding)); } else { rdfWriter.Save((IGraph)result, new StreamWriter(context.Response.OutputStream)); } } else if (result is ITripleStore) { IStoreWriter storeWriter = null; //Try and get a MIME Type Definition using the HTTP Requests Accept Header if (acceptTypes != null) { definition = MimeTypesHelper.GetDefinitions(acceptTypes).FirstOrDefault(d => d.CanWriteRdfDatasets); } if (definition == null) { //If no appropriate definition then use the GetStoreWriter method instead storeWriter = MimeTypesHelper.GetStoreWriter(acceptTypes, out ctype); } else { storeWriter = definition.GetRdfDatasetWriter(); } //Setup the writer if (definition != null) { ctype = definition.CanonicalMimeType; } context.Response.ContentType = ctype; HandlerHelper.ApplyWriterOptions(storeWriter, config); //Clear any existing Response context.Response.Clear(); //Send Triple Store to Client if (definition != null) { context.Response.ContentEncoding = definition.Encoding; storeWriter.Save((ITripleStore)result, new VDS.RDF.Storage.Params.StreamParams(context.Response.OutputStream, definition.Encoding)); } else { storeWriter.Save((ITripleStore)result, new VDS.RDF.Storage.Params.StreamParams(context.Response.OutputStream)); } } else if (result is ISparqlDataset) { //Wrap in a Triple Store and then call self so the Triple Store writing branch of this if gets called instead TripleStore store = new TripleStore(new DatasetGraphCollection((ISparqlDataset)result)); HandlerHelper.SendToClient(context, store, config); } else { throw new RdfOutputException("Unexpected Result Object of Type '" + result.GetType().ToString() + "' returned - unable to write Objects of this Type to the HTTP Response"); } }
/// <summary> /// Selects the Writer to use for sending the Graph to the Client /// </summary> /// <param name="definition">Selected MIME Type Definition</param> /// <returns></returns> /// <remarks> /// <para> /// Implementations may override this if they wish to substitute in an alternative writer for certain MIME types (e.g. as done by the <see cref="SchemaGraphHandler">SchemaGraphHandler</see>) /// </para> /// </remarks> protected virtual IRdfWriter SelectWriter(MimeTypeDefinition definition) { return(definition.GetRdfWriter()); }
/// <summary> /// Runs the task /// </summary> /// <returns></returns> protected override TaskResult RunTaskInternal() { MimeTypeDefinition def = MimeTypesHelper.GetDefinitionsByFileExtension(MimeTypesHelper.GetTrueFileExtension(this._file)).FirstOrDefault(d => d.CanWriteRdfDatasets); if (def == null) { throw new RdfOutputException("Cannot Export the Store to the selected File since dotNetRDF was unable to select a writer to use based on the File Extension"); } IStoreWriter writer = def.GetRdfDatasetWriter(); if (writer is IMultiThreadedWriter) { ((IMultiThreadedWriter)writer).UseMultiThreadedWriting = false; } TripleStore store = new TripleStore(); if (writer is TriXWriter) { //For TriX must load all into memory and then write out all at once foreach (Uri u in this.ListGraphs()) { Graph g = new Graph(); this._manager.LoadGraph(g, u); g.BaseUri = u; store.Add(g); this.Information = "Loading into memory prior to export, loaded " + store.Graphs.Sum(x => x.Triples.Count) + " Triple(s) in " + store.Graphs.Count + " Graph(s) so far..."; if (this.HasBeenCancelled) { this.Information = "Export Cancelled"; return(new TaskResult(true)); } } this.Information = "Exporting Data all at once, have " + store.Graphs.Sum(x => x.Triples.Count) + " Triple(s) in " + store.Graphs.Count + " Graph(s) to export..."; writer.Save(store, new StreamWriter(this._file)); this.Information = "Exported " + store.Graphs.Sum(x => x.Triples.Count) + " Triple(s) in " + store.Graphs.Count + " Graph(s)"; } else { if (File.Exists(this._file)) { File.Delete(this._file); } //For non-TriX formats assume it is safe to append one Graph at a time to the file int graphCount = 0, tripleCount = 0; foreach (Uri u in this.ListGraphs()) { using (FileStream stream = new FileStream(this._file, FileMode.Append)) { if (writer is IFormatterBasedWriter) { //Stream via a WriteThroughHandler this.Information = "Stream Exporting Graph " + (u != null ? u.AbsoluteUri : "Default"); WriteThroughHandler handler = new WriteThroughHandler(((IFormatterBasedWriter)writer).TripleFormatterType, new StreamWriter(stream), true); ExportProgressHandler progHandler = new ExportProgressHandler(handler, this, tripleCount); this._manager.LoadGraph(progHandler, u); graphCount++; tripleCount = progHandler.TripleCount; this.Information = "Finished Stream Exporting Graph " + (u != null ? u.AbsoluteUri : "Default") + ", exported " + tripleCount + " Triple(s) in " + graphCount + " Graph(s) so far..."; } else { //Load Graph into memory Graph g = new Graph(); g.BaseUri = u; this.Information = "Loading Graph " + (u != null ? u.AbsoluteUri : "Default"); this._manager.LoadGraph(g, u); g.BaseUri = u; if (this.HasBeenCancelled) { stream.Close(); this.Information = "Export Cancelled, exported " + tripleCount + " Triple(s) in " + graphCount + " Graph(s)"; return(new TaskResult(true)); } graphCount++; tripleCount += g.Triples.Count; //Save it store.Add(g); writer.Save(store, new StreamWriter(stream, def.Encoding)); store.Remove(u); this.Information = "Exporting Data graph by graph, exported " + tripleCount + " Triple(s) in " + graphCount + " Graph(s) so far..."; } //Check for cancellation if (this.HasBeenCancelled) { stream.Close(); this.Information = "Export Cancelled, exported " + tripleCount + " Triple(s) in " + graphCount + " Graph(s)"; return(new TaskResult(true)); } } } this.Information = "Exported " + tripleCount + " Triple(s) in " + graphCount + " Graph(s)"; } return(new TaskResult(true)); }
/// <summary> /// Processes the request by loading the Configuration in order to obtain the Graph to be served and then serving it to the client /// </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); //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; if (this._config.UserGroups.Any()) { //If we have user isAuth = HandlerHelper.IsAuthenticated(context, this._config.UserGroups); } if (!isAuth) { return; } //Check whether we can just send a 304 Not Modified if (HandlerHelper.CheckCachingHeaders(context, this._config.ETag, null)) { context.Response.StatusCode = (int)HttpStatusCode.NotModified; HandlerHelper.AddCachingHeaders(context, this._config.ETag, null); return; } try { String[] acceptTypes = HandlerHelper.GetAcceptTypes(context); //Retrieve an appropriate MIME Type Definition which can be used to get a Writer MimeTypeDefinition definition = MimeTypesHelper.GetDefinitions(acceptTypes).FirstOrDefault(d => d.CanWriteRdf); if (definition == null) { throw new RdfWriterSelectionException("No MIME Type Definitions have a registered RDF Writer for the MIME Types specified in the HTTP Accept Header"); } IRdfWriter writer = this.SelectWriter(definition); HandlerHelper.ApplyWriterOptions(writer, this._config); IGraph g = this.ProcessGraph(this._config.Graph); if (this._config.ETag == null) { this._config.ETag = this.ComputeETag(g); } //Serve the Graph to the User context.Response.ContentType = definition.CanonicalMimeType; HandlerHelper.AddCachingHeaders(context, this._config.ETag, null); if (writer is IHtmlWriter) { if (!this._config.Stylesheet.Equals(String.Empty)) { ((IHtmlWriter)writer).Stylesheet = this._config.Stylesheet; } } context.Response.ContentEncoding = definition.Encoding; HandlerHelper.ApplyWriterOptions(writer, this._config); writer.Save(g, new StreamWriter(context.Response.OutputStream, definition.Encoding)); this.UpdateConfig(context); } catch (RdfWriterSelectionException) { context.Response.StatusCode = (int)HttpStatusCode.NotAcceptable; } catch { 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); } }
/// <summary> /// Selects the Writer to use for sending the Graph to the Client /// </summary> /// <param name="definition">Selected MIME Type Definition</param> /// <returns></returns> /// <remarks> /// <para> /// Implementations may override this if they wish to substitute in an alternative writer for certain MIME types (e.g. as done by the <see cref="SchemaGraphHandler">SchemaGraphHandler</see>) /// </para> /// </remarks> protected virtual IRdfWriter SelectWriter(MimeTypeDefinition definition) { return definition.GetRdfWriter(); }