public void ItAllowsEndpointErrorsToBeIgnored() { var endpoint = new FederatedSparqlRemoteEndpoint(new[] { new SparqlRemoteEndpoint(new Uri(_fixture.Server1.Urls[0] + "/query")), new SparqlRemoteEndpoint(new Uri(_fixture.Server2.Urls[0] + "/fail")), }) { IgnoreFailedRequests = true }; var results = endpoint.QueryWithResultSet("SELECT * WHERE {?s ?p ?o}"); results.Should().NotBeNull().And.HaveCount(1); _fixture.Server1.FindLogEntries(new RequestMessagePathMatcher(MatchBehaviour.AcceptOnMatch, "/query")) .Should().HaveCount(1).And.Contain(x => x.RequestMessage.Method.Equals("get", StringComparison.InvariantCultureIgnoreCase)); }
private bool SetupSparqlEndpointData() { try { FederatedSparqlRemoteEndpoint federatedSparqlRemoteEndpoint = new FederatedSparqlRemoteEndpoint(_testSparqlEndpoints); var response = federatedSparqlRemoteEndpoint.QueryWithResultSet("select ?s where {?s ?p ?o} limit 1"); if (response.Count() == 3) { return(true); } return(false); } catch (Exception) { return(false); } }
/// <summary> /// Tries to load a SPARQL Endpoint based on information from the Configuration Graph. /// </summary> /// <param name="g">Configuration Graph.</param> /// <param name="objNode">Object Node.</param> /// <param name="targetType">Target Type.</param> /// <param name="obj">Output Object.</param> /// <returns></returns> public bool TryLoadObject(IGraph g, INode objNode, Type targetType, out object obj) { BaseEndpoint endpoint = null; obj = null; switch (targetType.FullName) { case QueryEndpoint: String queryEndpointUri = ConfigurationLoader.GetConfigurationValue(g, objNode, new INode[] { g.CreateUriNode(UriFactory.Create(ConfigurationLoader.PropertyQueryEndpointUri)), g.CreateUriNode(UriFactory.Create(ConfigurationLoader.PropertyEndpointUri)) }); if (queryEndpointUri == null) { return(false); } // Get Default/Named Graphs if specified IEnumerable <String> defaultGraphs = from n in ConfigurationLoader.GetConfigurationData(g, objNode, g.CreateUriNode(UriFactory.Create(ConfigurationLoader.PropertyDefaultGraphUri))) select n.ToString(); IEnumerable <String> namedGraphs = from n in ConfigurationLoader.GetConfigurationData(g, objNode, g.CreateUriNode(UriFactory.Create(ConfigurationLoader.PropertyNamedGraphUri))) select n.ToString(); endpoint = new SparqlRemoteEndpoint(UriFactory.Create(queryEndpointUri), defaultGraphs, namedGraphs); break; case UpdateEndpoint: String updateEndpointUri = ConfigurationLoader.GetConfigurationValue(g, objNode, new INode[] { g.CreateUriNode(UriFactory.Create(ConfigurationLoader.PropertyUpdateEndpointUri)), g.CreateUriNode(UriFactory.Create(ConfigurationLoader.PropertyEndpointUri)) }); if (updateEndpointUri == null) { return(false); } endpoint = new SparqlRemoteUpdateEndpoint(UriFactory.Create(updateEndpointUri)); break; case FederatedEndpoint: IEnumerable <INode> endpoints = ConfigurationLoader.GetConfigurationData(g, objNode, g.CreateUriNode(UriFactory.Create(ConfigurationLoader.PropertyQueryEndpoint))) .Concat(ConfigurationLoader.GetConfigurationData(g, objNode, g.CreateUriNode(UriFactory.Create(ConfigurationLoader.PropertyEndpoint)))); foreach (INode e in endpoints) { Object temp = ConfigurationLoader.LoadObject(g, e); if (temp is SparqlRemoteEndpoint) { if (endpoint == null) { endpoint = new FederatedSparqlRemoteEndpoint((SparqlRemoteEndpoint)temp); } else { ((FederatedSparqlRemoteEndpoint)endpoint).AddEndpoint((SparqlRemoteEndpoint)temp); } } else { throw new DotNetRdfConfigurationException("Unable to load the SPARQL Endpoint identified by the Node '" + e.ToString() + "' as one of the values for the dnr:queryEndpoint/dnr:endpoint property points to an Object which cannot be loaded as an object which is a SparqlRemoteEndpoint"); } } break; } if (endpoint != null) { // Are there any credentials specified? String user, pwd; ConfigurationLoader.GetUsernameAndPassword(g, objNode, true, out user, out pwd); if (user != null && pwd != null) { endpoint.SetCredentials(user, pwd); } // Is there a Proxy Server specified INode proxyNode = ConfigurationLoader.GetConfigurationNode(g, objNode, g.CreateUriNode(UriFactory.Create(ConfigurationLoader.PropertyProxy))); if (proxyNode != null) { Object proxy = ConfigurationLoader.LoadObject(g, proxyNode); if (proxy is IWebProxy) { endpoint.Proxy = (IWebProxy)proxy; // Are we supposed to use the same credentials for the proxy as for the endpoint? bool useCredentialsForProxy = ConfigurationLoader.GetConfigurationBoolean(g, objNode, g.CreateUriNode(UriFactory.Create(ConfigurationLoader.PropertyUseCredentialsForProxy)), false); if (useCredentialsForProxy) { endpoint.UseCredentialsForProxy = true; } } else { throw new DotNetRdfConfigurationException("Unable to load SPARQL Endpoint identified by the Node '" + objNode.ToString() + "' as the value for the dnr:proxy property points to an Object which cannot be loaded as an object of type WebProxy"); } } } obj = endpoint; return(endpoint != null); }
/// <summary> /// Evaluates the Service Clause by generating instance(s) of <see cref="SparqlRemoteEndpoint">SparqlRemoteEndpoint</see> as required and issuing the query to the remote endpoint(s). /// </summary> /// <param name="context">Evaluation Context.</param> /// <returns></returns> public BaseMultiset Evaluate(SparqlEvaluationContext context) { bool bypassSilent = false; try { SparqlRemoteEndpoint endpoint; Uri endpointUri; String baseUri = (context.Query.BaseUri == null) ? String.Empty : context.Query.BaseUri.AbsoluteUri; SparqlParameterizedString sparqlQuery = new SparqlParameterizedString("SELECT * WHERE "); String pattern = _pattern.ToString(); pattern = pattern.Substring(pattern.IndexOf('{')); sparqlQuery.CommandText += pattern; // Pass through LIMIT and OFFSET to the remote service if (context.Query.Limit >= 0) { // Calculate a LIMIT which is the LIMIT plus the OFFSET // We'll apply OFFSET locally so don't pass that through explicitly int limit = context.Query.Limit; if (context.Query.Offset > 0) { limit += context.Query.Offset; } sparqlQuery.CommandText += " LIMIT " + limit; } // Select which service to use if (_endpointSpecifier.TokenType == Token.URI) { endpointUri = UriFactory.Create(Tools.ResolveUri(_endpointSpecifier.Value, baseUri)); endpoint = new SparqlRemoteEndpoint(endpointUri); } else if (_endpointSpecifier.TokenType == Token.VARIABLE) { // Get all the URIs that are bound to this Variable in the Input String var = _endpointSpecifier.Value.Substring(1); if (!context.InputMultiset.ContainsVariable(var)) { throw new RdfQueryException("Cannot evaluate a SERVICE clause which uses a Variable as the Service specifier when the Variable is unbound"); } List <IUriNode> services = new List <IUriNode>(); foreach (ISet s in context.InputMultiset.Sets) { if (s.ContainsVariable(var)) { if (s[var].NodeType == NodeType.Uri) { services.Add((IUriNode)s[var]); } } } services = services.Distinct().ToList(); // Now generate a Federated Remote Endpoint List <SparqlRemoteEndpoint> serviceEndpoints = new List <SparqlRemoteEndpoint>(); services.ForEach(u => serviceEndpoints.Add(new SparqlRemoteEndpoint(u.Uri))); endpoint = new FederatedSparqlRemoteEndpoint(serviceEndpoints); } else { // Note that we must bypass the SILENT operator in this case as this is not an evaluation failure // but a query syntax error bypassSilent = true; throw new RdfQueryException("SERVICE Specifier must be a URI/Variable Token but a " + _endpointSpecifier.GetType().ToString() + " Token was provided"); } // Where possible do substitution and execution to get accurate and correct SERVICE results context.OutputMultiset = new Multiset(); List <String> existingVars = (from v in _pattern.Variables where context.InputMultiset.ContainsVariable(v) select v).ToList(); if (existingVars.Any() || context.Query.Bindings != null) { // Pre-bound variables/BINDINGS clause so do substitution and execution // Build the set of possible bindings HashSet <ISet> bindings = new HashSet <ISet>(); if (context.Query.Bindings != null && !_pattern.Variables.IsDisjoint(context.Query.Bindings.Variables)) { // Possible Bindings comes from BINDINGS clause // In this case each possibility is a distinct binding tuple defined in the BINDINGS clause foreach (BindingTuple tuple in context.Query.Bindings.Tuples) { bindings.Add(new Set(tuple)); } } else { // Possible Bindings get built from current input (if there was a BINDINGS clause the variables it defines are not in this SERVICE clause) // In this case each possibility only contains Variables bound so far foreach (ISet s in context.InputMultiset.Sets) { Set t = new Set(); foreach (String var in existingVars) { t.Add(var, s[var]); } bindings.Add(t); } } // Execute the Query for every possible Binding and build up our Output Multiset from all the results foreach (ISet s in bindings) { // Q: Should we continue processing here if and when we hit an error? foreach (String var in s.Variables) { sparqlQuery.SetVariable(var, s[var]); } SparqlResultSet results = endpoint.QueryWithResultSet(sparqlQuery.ToString()); context.CheckTimeout(); foreach (SparqlResult r in results) { Set t = new Set(r); foreach (String var in s.Variables) { t.Add(var, s[var]); } context.OutputMultiset.Add(t); } } return(context.OutputMultiset); } else { // No pre-bound variables/BINDINGS clause so just execute the query // Try and get a Result Set from the Service SparqlResultSet results = endpoint.QueryWithResultSet(sparqlQuery.ToString()); // Transform this Result Set back into a Multiset foreach (SparqlResult r in results.Results) { context.OutputMultiset.Add(new Set(r)); } return(context.OutputMultiset); } } catch (Exception ex) { if (_silent && !bypassSilent) { // If Evaluation Errors are SILENT is specified then a Multiset containing a single set with all values unbound is returned // Unless some of the SPARQL queries did return results in which we just return the results we did obtain if (context.OutputMultiset.IsEmpty) { Set s = new Set(); foreach (String var in _pattern.Variables.Distinct()) { s.Add(var, null); } context.OutputMultiset.Add(s); } return(context.OutputMultiset); } else { throw new RdfQueryException("Query execution failed because evaluating a SERVICE clause failed - this may be due to an error with the remote service", ex); } } }
/// <summary> /// Evaluates the Service Clause by generating instance(s) of <see cref="SparqlRemoteEndpoint">SparqlRemoteEndpoint</see> as required and issuing the query to the remote endpoint(s) /// </summary> /// <param name="context">Evaluation Context</param> /// <returns></returns> public BaseMultiset Evaluate(SparqlEvaluationContext context) { bool bypassSilent = false; try { #if SILVERLIGHT throw new PlatformNotSupportedException("SERVICE is not currently supported under Silverlight"); #else SparqlRemoteEndpoint endpoint; Uri endpointUri; String baseUri = (context.Query.BaseUri == null) ? String.Empty : context.Query.BaseUri.ToString(); SparqlParameterizedString sparqlQuery = new SparqlParameterizedString("SELECT * WHERE "); String pattern = this._pattern.ToString(); pattern = pattern.Substring(pattern.IndexOf('{')); sparqlQuery.CommandText += pattern; //Pass through LIMIT and OFFSET to the remote service if (context.Query.Limit >= 0) { //Calculate a LIMIT which is the LIMIT plus the OFFSET //We'll apply OFFSET locally so don't pass that through explicitly int limit = context.Query.Limit; if (context.Query.Offset > 0) limit += context.Query.Offset; sparqlQuery.CommandText += " LIMIT " + limit; } //Select which service to use if (this._endpointSpecifier.TokenType == Token.URI) { endpointUri = UriFactory.Create(Tools.ResolveUri(this._endpointSpecifier.Value, baseUri)); endpoint = new SparqlRemoteEndpoint(endpointUri); } else if (this._endpointSpecifier.TokenType == Token.VARIABLE) { //Get all the URIs that are bound to this Variable in the Input String var = this._endpointSpecifier.Value.Substring(1); if (!context.InputMultiset.ContainsVariable(var)) throw new RdfQueryException("Cannot evaluate a SERVICE clause which uses a Variable as the Service specifier when the Variable is unbound"); List<IUriNode> services = new List<IUriNode>(); foreach (ISet s in context.InputMultiset.Sets) { if (s.ContainsVariable(var)) { if (s[var].NodeType == NodeType.Uri) { services.Add((IUriNode)s[var]); } } } services = services.Distinct().ToList(); //Now generate a Federated Remote Endpoint List<SparqlRemoteEndpoint> serviceEndpoints = new List<SparqlRemoteEndpoint>(); services.ForEach(u => serviceEndpoints.Add(new SparqlRemoteEndpoint(u.Uri))); endpoint = new FederatedSparqlRemoteEndpoint(serviceEndpoints); } else { //Note that we must bypass the SILENT operator in this case as this is not an evaluation failure //but a query syntax error bypassSilent = true; throw new RdfQueryException("SERVICE Specifier must be a URI/Variable Token but a " + this._endpointSpecifier.GetType().ToString() + " Token was provided"); } //Where possible do substitution and execution to get accurate and correct SERVICE results context.OutputMultiset = new Multiset(); List<String> existingVars = (from v in this._pattern.Variables where context.InputMultiset.ContainsVariable(v) select v).ToList(); if (existingVars.Any() || context.Query.Bindings != null) { //Pre-bound variables/BINDINGS clause so do substitution and execution //Build the set of possible bindings HashSet<ISet> bindings = new HashSet<ISet>(); if (context.Query.Bindings != null && !this._pattern.Variables.IsDisjoint(context.Query.Bindings.Variables)) { //Possible Bindings comes from BINDINGS clause //In this case each possibility is a distinct binding tuple defined in the BINDINGS clause foreach (BindingTuple tuple in context.Query.Bindings.Tuples) { bindings.Add(new Set(tuple)); } } else { //Possible Bindings get built from current input (if there was a BINDINGS clause the variables it defines are not in this SERVICE clause) //In this case each possibility only contains Variables bound so far foreach (ISet s in context.InputMultiset.Sets) { Set t = new Set(); foreach (String var in existingVars) { t.Add(var, s[var]); } bindings.Add(t); } } //Execute the Query for every possible Binding and build up our Output Multiset from all the results foreach (ISet s in bindings) { //Q: Should we continue processing here if and when we hit an error? foreach (String var in s.Variables) { sparqlQuery.SetVariable(var, s[var]); } SparqlResultSet results = endpoint.QueryWithResultSet(sparqlQuery.ToString()); context.CheckTimeout(); foreach (SparqlResult r in results) { Set t = new Set(r); foreach (String var in s.Variables) { t.Add(var, s[var]); } context.OutputMultiset.Add(t); } } return context.OutputMultiset; } else { //No pre-bound variables/BINDINGS clause so just execute the query //Try and get a Result Set from the Service SparqlResultSet results = endpoint.QueryWithResultSet(sparqlQuery.ToString()); //Transform this Result Set back into a Multiset foreach (SparqlResult r in results.Results) { context.OutputMultiset.Add(new Set(r)); } return context.OutputMultiset; } #endif } catch (Exception ex) { if (this._silent && !bypassSilent) { //If Evaluation Errors are SILENT is specified then a Multiset containing a single set with all values unbound is returned //Unless some of the SPARQL queries did return results in which we just return the results we did obtain if (context.OutputMultiset.IsEmpty) { Set s = new Set(); foreach (String var in this._pattern.Variables.Distinct()) { s.Add(var, null); } context.OutputMultiset.Add(s); } return context.OutputMultiset; } else { throw new RdfQueryException("Query execution failed because evaluating a SERVICE clause failed - this may be due to an error with the remote service", ex); } } }