public void ParsingDataUri1() { String rdfFragment = "@prefix : <http://example.org/> . :subject :predicate :object ."; String rdfBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(rdfFragment)); String rdfAscii = Uri.EscapeDataString(rdfFragment); List <String> uris = new List <string>() { "data:text/turtle;charset=UTF-8;base64," + rdfBase64, "data:text/turtle;base64," + rdfBase64, "data:;base64," + rdfBase64, "data:text/turtle;charset=UTF-8," + rdfAscii, "data:text/tutle," + rdfAscii, "data:," + rdfAscii }; foreach (String uri in uris) { Uri u = new Uri(uri); Console.WriteLine("Testing URI " + u.AbsoluteUri); Graph g = new Graph(); DataUriLoader.Load(g, u); Assert.Equal(1, g.Triples.Count); Console.WriteLine("Triples produced:"); foreach (Triple t in g.Triples) { Console.WriteLine(t.ToString()); } Console.WriteLine(); } }
/// <summary> /// Loads RDF data into a Graph from a data: URI /// </summary> /// <param name="g">Graph to load into</param> /// <param name="u">URI to load from</param> /// <remarks> /// Invokes the normal <see cref="UriLoader">UriLoader</see> instead if a the URI provided is not a data: URI /// </remarks> /// <exception cref="UriFormatException">Thrown if the metadata portion of the URI which indicates the MIME Type, Character Set and whether Base64 encoding is used is malformed</exception> public static void Load(IGraph g, Uri u) { if (u == null) { throw new RdfParseException("Cannot load RDF from a null URI"); } if (g == null) { throw new RdfParseException("Cannot read RDF into a null Graph"); } DataUriLoader.Load(new GraphHandler(g), u); }
/// <summary> /// Attempts to load a RDF Graph from a URI asynchronously /// </summary> /// <param name="g">Graph to assert triple in</param> /// <param name="u">URI to load from</param> /// <param name="parser">Parser to use</param> /// <param name="callback">Callback to invoke when the operation completes</param> /// <param name="state">State to pass to the callback</param> /// <remarks> /// <para> /// Uses the supplied parser to attempt parsing regardless of the actual Content Type returned /// </para> /// <para> /// In the event that the URI is a File URI the <see cref="FileLoader">FileLoader</see> will be used instead. If the URI is a Data URI then the <see cref="DataUriLoader">DataUriLoader</see> will be used instead. /// </para> /// <para> /// <strong>Note:</strong> UriLoader will assign the Graph the source URI as it's Base URI unless the Graph already has a Base URI or is non-empty prior to attempting parsing. Note that any Base URI specified in the RDF contained in the file will override this initial Base URI. In some cases this may lead to invalid RDF being accepted and generating strange relative URIs, if you encounter this either set a Base URI prior to calling this method or create an instance of the relevant parser and invoke it directly. /// </para> /// <para> /// If the loading completes normally the callback will be invoked normally, if an error occurs it will be invoked and passed an instance of <see cref="AsyncError"/> as the state which contains details of the error and the original state. /// </para> /// </remarks> public static void Load(IGraph g, Uri u, IRdfReader parser, GraphCallback callback, Object state) { if (g == null) { throw new RdfParseException("Cannot read RDF into a null Graph"); } if (u == null) { throw new RdfParseException("Cannot read RDF from a null URI"); } #if SILVERLIGHT if (u.IsFile()) #else if (u.IsFile) #endif { #if PORTABLE throw new PlatformNotSupportedException("FileLoader is not supported by the Portable Class Library build"); #else //Invoke FileLoader instead UriLoader.RaiseWarning("This is a file: URI so invoking the FileLoader instead"); if (Path.DirectorySeparatorChar == '/') { FileLoader.Load(g, u.AbsoluteUri.Substring(7), parser); } else { FileLoader.Load(g, u.AbsoluteUri.Substring(8), parser); } //FileLoader.Load() will run synchronously so once this completes we can invoke the callback callback(g, state); return; #endif } if (u.Scheme.Equals("data")) { //Invoke DataUriLoader instead RaiseWarning("This is a data: URI so invoking the DataUriLoader instead"); DataUriLoader.Load(g, u); //After DataUriLoader.Load() has run (which happens synchronously) can invoke the callback callback(g, state); return; } //Set Base URI if necessary if (g.BaseUri == null && g.IsEmpty) { g.BaseUri = u; } UriLoader.Load(new GraphHandler(g), u, parser, (_, s) => callback(g, s), state); }
/// <summary> /// Attempts to load a RDF Graph from the given URI into the given Graph /// </summary> /// <param name="g">Graph to assert Triples in</param> /// <param name="u">URI to attempt to get RDF from</param> /// <param name="parser">Parser to use</param> /// <remarks> /// <para> /// Uses the supplied parser to attempt parsing regardless of the actual Content Type returned /// </para> /// <para> /// In the event that the URI is a File URI the <see cref="FileLoader">FileLoader</see> will be used instead /// </para> /// <para> /// If the URI is a Data URI then the <see cref="DataUriLoader">DataUriLoader</see> will be used instead. /// </para> /// </remarks> public static void Load(IGraph g, Uri u, IRdfReader parser) { if (g == null) { throw new RdfParseException("Cannot read RDF into a null Graph"); } if (u == null) { throw new RdfParseException("Cannot load RDF from a null URI"); } #if SILVERLIGHT if (u.IsFile()) #else if (u.IsFile) #endif { //Invoke FileLoader instead RaiseWarning("This is a file: URI so invoking the FileLoader instead"); if (Path.DirectorySeparatorChar == '/') { FileLoader.Load(g, u.ToString().Substring(7), parser); } else { FileLoader.Load(g, u.ToString().Substring(8), parser); } return; } if (u.Scheme.Equals("data")) { //Invoke DataUriLoader instead RaiseWarning("This is a data: URI so invoking the DataUriLoader instead"); DataUriLoader.Load(g, u); return; } //Set Base Uri if necessary if (g.BaseUri == null && g.IsEmpty) { g.BaseUri = u; } UriLoader.Load(new GraphHandler(g), u, parser); }
/// <summary> /// Attempts to load a RDF Graph from the given URI using a RDF Handler /// </summary> /// <param name="handler">RDF Handler to use</param> /// <param name="u">URI to attempt to get RDF from</param> /// <param name="parser">Parser to use</param> /// <remarks> /// <para> /// Uses the supplied parser to attempt parsing regardless of the actual Content Type returned /// </para> /// <para> /// In the event that the URI is a File URI the <see cref="FileLoader">FileLoader</see> will be used instead /// </para> /// <para> /// If the URI is a Data URI then the <see cref="DataUriLoader">DataUriLoader</see> will be used instead. /// </para> /// </remarks> public static void Load(IRdfHandler handler, Uri u, IRdfReader parser) { if (handler == null) { throw new RdfParseException("Cannot read RDF using a null RDF Handler"); } if (u == null) { throw new RdfParseException("Cannot load RDF from a null URI"); } try { #if SILVERLIGHT if (u.IsFile()) #else if (u.IsFile) #endif { //Invoke FileLoader instead RaiseWarning("This is a file: URI so invoking the FileLoader instead"); if (Path.DirectorySeparatorChar == '/') { FileLoader.Load(handler, u.ToString().Substring(7), parser); } else { FileLoader.Load(handler, u.ToString().Substring(8), parser); } return; } if (u.Scheme.Equals("data")) { //Invoke DataUriLoader instead RaiseWarning("This is a data: URI so invoking the DataUriLoader instead"); DataUriLoader.Load(handler, u); return; } //Sanitise the URI to remove any Fragment ID u = Tools.StripUriFragment(u); #if !NO_URICACHE //Use Cache if possible String etag = String.Empty; String local = null; if (Options.UriLoaderCaching) { if (_cache.HasETag(u)) { //Get the ETag and then we'll include an If-None-Match header in our request etag = _cache.GetETag(u); } else if (_cache.HasLocalCopy(u, true)) { //Just try loading from the local copy local = _cache.GetLocalCopy(u); if (local != null) { try { FileLoader.Load(handler, local, new TurtleParser()); } catch { //If we get an Exception we failed to access the file successfully _cache.RemoveETag(u); _cache.RemoveLocalCopy(u); UriLoader.Load(handler, u, parser); } return; } } } #endif //Set-up the Request HttpWebRequest httpRequest; httpRequest = (HttpWebRequest)WebRequest.Create(u); //Want to ask for RDF formats if (parser != null) { //If a non-null parser set up a HTTP Header that is just for the given parser httpRequest.Accept = MimeTypesHelper.CustomHttpAcceptHeader(parser); } else { httpRequest.Accept = MimeTypesHelper.HttpAcceptHeader; } #if !NO_URICACHE if (Options.UriLoaderCaching) { if (!etag.Equals(String.Empty)) { httpRequest.Headers.Add(HttpRequestHeader.IfNoneMatch, etag); } } #endif //Use HTTP GET httpRequest.Method = "GET"; #if !SILVERLIGHT httpRequest.Timeout = Options.UriLoaderTimeout; #endif if (_userAgent != null && !_userAgent.Equals(String.Empty)) { httpRequest.UserAgent = _userAgent; } #if DEBUG //HTTP Debugging if (Options.HttpDebugging) { Tools.HttpDebugRequest(httpRequest); } #endif using (HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse()) { #if DEBUG //HTTP Debugging if (Options.HttpDebugging) { Tools.HttpDebugResponse(httpResponse); } #endif #if !NO_URICACHE if (Options.UriLoaderCaching) { //Are we using ETag based caching? if (!etag.Equals(String.Empty)) { //Did we get a Not-Modified response? if (httpResponse.StatusCode == HttpStatusCode.NotModified) { //If so then we need to load the Local Copy assuming it exists? if (_cache.HasLocalCopy(u, false)) { local = _cache.GetLocalCopy(u); try { FileLoader.Load(handler, local, new TurtleParser()); } catch { //If we get an Exception we failed to access the file successfully _cache.RemoveETag(u); _cache.RemoveLocalCopy(u); UriLoader.Load(handler, u, parser); } return; } else { //If the local copy didn't exist then we need to redo the response without //the ETag as we've lost the cached copy somehow _cache.RemoveETag(u); UriLoader.Load(handler, u, parser); return; } } //If we didn't get a Not-Modified response then we'll continue and parse the new response } } #endif //Get a Parser and Load the RDF if (parser == null) { //Only need to auto-detect the parser if a specific one wasn't specified parser = MimeTypesHelper.GetParser(httpResponse.ContentType); } parser.Warning += RaiseWarning; #if !NO_URICACHE //To do caching we ask the cache to give us a handler and then we tie it to IRdfHandler cacheHandler = _cache.ToCache(u, Tools.StripUriFragment(httpResponse.ResponseUri), httpResponse.Headers["ETag"]); if (cacheHandler != null) { //Note: We can ONLY use caching when we know that the Handler will accept all the data returned //i.e. if the Handler may trim the data in some way then we shouldn't cache the data returned if (handler.AcceptsAll) { handler = new MultiHandler(new IRdfHandler[] { handler, cacheHandler }); } else { cacheHandler = null; } } try { #endif parser.Load(handler, new StreamReader(httpResponse.GetResponseStream())); #if !NO_URICACHE } catch { //If we were trying to cache the response and something went wrong discard the cached copy _cache.RemoveETag(u); _cache.RemoveETag(Tools.StripUriFragment(httpResponse.ResponseUri)); _cache.RemoveLocalCopy(u); _cache.RemoveLocalCopy(Tools.StripUriFragment(httpResponse.ResponseUri)); } #endif } } catch (UriFormatException uriEx) { //Uri Format Invalid throw new RdfParseException("Unable to load from the given URI '" + u.ToString() + "' since it's format was invalid", uriEx); } catch (WebException webEx) { #if DEBUG if (webEx.Response != null && Options.HttpDebugging) { Tools.HttpDebugResponse((HttpWebResponse)webEx.Response); } #endif #if !NO_URICACHE if (webEx.Response != null) { if (((HttpWebResponse)webEx.Response).StatusCode == HttpStatusCode.NotModified) { //If so then we need to load the Local Copy assuming it exists? if (_cache.HasLocalCopy(u, false)) { String local = _cache.GetLocalCopy(u); try { FileLoader.Load(handler, local, new TurtleParser()); } catch { //If we get an Exception we failed to access the file successfully _cache.RemoveETag(u); _cache.RemoveLocalCopy(u); UriLoader.Load(handler, u, parser); } return; } else { //If the local copy didn't exist then we need to redo the response without //the ETag as we've lost the cached copy somehow _cache.RemoveETag(u); UriLoader.Load(handler, u, parser); return; } } } #endif //Some sort of HTTP Error occurred throw new WebException("A HTTP Error occurred resolving the URI '" + u.ToString() + "'", webEx); } }
/// <summary> /// Attempts to load a RDF dataset asynchronously from the given URI using a RDF Handler. /// </summary> /// <param name="handler">RDF Handler to use.</param> /// <param name="u">URI to attempt to get a RDF dataset from.</param> /// <param name="parser">Parser to use to parse the RDF dataset.</param> /// <param name="callback">Callback to invoke when the operation completes.</param> /// <param name="state">State to pass to the callback.</param> /// <remarks> /// <para> /// If the <paramref name="parser"/> parameter is set to null then this method attempts to select the relevant Store Parser based on the Content Type header returned in the HTTP Response. /// </para> /// <para> /// If you know ahead of time the Content Type you can explicitly pass in the parser to use. /// </para> /// <para> /// If the loading completes normally the callback will be invoked normally, if an error occurs it will be invoked and passed an instance of <see cref="AsyncError"/> as the state which contains details of the error and the original state. /// </para> /// </remarks> public static void Load(IRdfHandler handler, Uri u, IStoreReader parser, RdfHandlerCallback callback, Object state) { if (u == null) { throw new RdfParseException("Cannot read a RDF dataset from a null URI"); } if (handler == null) { throw new RdfParseException("Cannot read a RDF dataset using a null RDF handler"); } try { if (u.IsFile) { // Invoke FileLoader instead RaiseWarning("This is a file: URI so invoking the FileLoader instead"); if (Path.DirectorySeparatorChar == '/') { FileLoader.Load(handler, u.AbsoluteUri.Substring(7), parser); } else { FileLoader.Load(handler, u.AbsoluteUri.Substring(8), parser); } // FileLoader.Load() will run synchronously so once this completes we can invoke the callback callback(handler, state); return; } if (u.Scheme.Equals("data")) { // Invoke DataUriLoader instead RaiseWarning("This is a data: URI so invoking the DataUriLoader instead"); DataUriLoader.Load(handler, u); // After DataUriLoader.Load() has run (which happens synchronously) can invoke the callback callback(handler, state); return; } // Sanitise the URI to remove any Fragment ID u = Tools.StripUriFragment(u); // Setup the Request HttpWebRequest request = (HttpWebRequest)WebRequest.Create(u); // Want to ask for RDF dataset formats if (parser != null) { // If a non-null parser set up a HTTP Header that is just for the given parser request.Accept = MimeTypesHelper.CustomHttpAcceptHeader(parser); } else { request.Accept = MimeTypesHelper.HttpAcceptHeader; } // Use HTTP GET request.Method = "GET"; #if !NETCORE request.Timeout = Options.UriLoaderTimeout; #endif if (_userAgent != null && !_userAgent.Equals(String.Empty)) { #if NETCORE request.Headers[HttpRequestHeader.UserAgent] = _userAgent; #else request.UserAgent = _userAgent; #endif } Tools.HttpDebugRequest(request); try { request.BeginGetResponse(result => { try { using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result)) { Tools.HttpDebugResponse(response); // Get a Parser and load the RDF if (parser == null) { try { // Only need to auto-detect the parser if a specific one wasn't specified parser = MimeTypesHelper.GetStoreParser(response.ContentType); parser.Warning += RaiseWarning; parser.Load(handler, new StreamReader(response.GetResponseStream())); } catch (RdfParserSelectionException) { RaiseStoreWarning("Unable to select a RDF Dataset parser based on Content-Type: " + response.ContentType + " - seeing if the content is an RDF Graph instead"); try { // If not a RDF Dataset format see if it is a Graph IRdfReader rdfParser = MimeTypesHelper.GetParser(response.ContentType); rdfParser.Load(handler, new StreamReader(response.GetResponseStream())); } catch (RdfParserSelectionException) { String data = new StreamReader(response.GetResponseStream()).ReadToEnd(); parser = StringParser.GetDatasetParser(data); parser.Warning += RaiseStoreWarning; parser.Load(handler, new StringReader(data)); } } } else { parser.Warning += RaiseStoreWarning; parser.Load(handler, new StreamReader(response.GetResponseStream())); } // Finally can invoke the callback callback(handler, state); } } catch (WebException webEx) { if (webEx.Response != null) { Tools.HttpDebugResponse((HttpWebResponse)webEx.Response); } callback(handler, new AsyncError(new RdfParseException("A HTTP Error occurred loading the URI '" + u.AbsoluteUri + "' asynchronously, see inner exeption for details", webEx), state)); } catch (Exception ex) { callback(handler, new AsyncError(new RdfParseException("Unexpected error while loading the URI '" + u.AbsoluteUri + "' asynchronously, see inner exception for details", ex), state)); } }, null); } catch (WebException webEx) { if (webEx.Response != null) { Tools.HttpDebugResponse((HttpWebResponse)webEx.Response); } callback(handler, new AsyncError(new RdfParseException("A HTTP Error occurred loading the URI '" + u.AbsoluteUri + "' asynchronously, see inner exeption for details", webEx), state)); } catch (Exception ex) { callback(handler, new AsyncError(new RdfParseException("Unexpected error while loading the URI '" + u.AbsoluteUri + "' asynchronously, see inner exception for details", ex), state)); } } catch (UriFormatException uriEx) { // Uri Format Invalid throw new RdfException("Unable to load from the given URI '" + u.AbsoluteUri + "' since it's format was invalid, see inner exception for details", uriEx); } }
/// <summary> /// Attempts to load a RDF Graph from a URI asynchronously using an RDF Handler /// </summary> /// <param name="handler">RDF Handler to use</param> /// <param name="u">URI to load from</param> /// <param name="parser">Parser to use</param> /// <param name="callback">Callback to invoke when the operation completes</param> /// <param name="state">State to pass to the callback</param> /// <remarks> /// <para> /// Uses the supplied parser to attempt parsing regardless of the actual Content Type returned /// </para> /// <para> /// In the event that the URI is a File URI the <see cref="FileLoader">FileLoader</see> will be used instead /// </para> /// <para> /// If the URI is a Data URI then the <see cref="DataUriLoader">DataUriLoader</see> will be used instead. /// </para> /// <para> /// If the loading completes normally the callback will be invoked normally, if an error occurs it will be invoked and passed an instance of <see cref="AsyncError"/> as the state which contains details of the error and the original state. /// </para> /// </remarks> public static void Load(IRdfHandler handler, Uri u, IRdfReader parser, RdfHandlerCallback callback, Object state) { if (handler == null) { throw new RdfParseException("Cannot read RDF using a null RDF Handler"); } if (u == null) { throw new RdfParseException("Cannot load RDF from a null URI"); } try { #if SILVERLIGHT if (u.IsFile()) #else if (u.IsFile) #endif { #if PORTABLE throw new PlatformNotSupportedException("FileLoader is not supported by the Portable Class Library build"); #else //Invoke FileLoader instead RaiseWarning("This is a file: URI so invoking the FileLoader instead"); if (Path.DirectorySeparatorChar == '/') { FileLoader.Load(handler, u.AbsoluteUri.Substring(7), parser); } else { FileLoader.Load(handler, u.AbsoluteUri.Substring(8), parser); } //FileLoader.Load() will run synchronously so once this completes we can invoke the callback callback(handler, state); return; #endif } if (u.Scheme.Equals("data")) { //Invoke DataUriLoader instead RaiseWarning("This is a data: URI so invoking the DataUriLoader instead"); DataUriLoader.Load(handler, u); //After DataUriLoader.Load() has run (which happens synchronously) can invoke the callback callback(handler, state); return; } //Sanitise the URI to remove any Fragment ID u = Tools.StripUriFragment(u); //TODO: Add use of Cache into here, this is tricky because this code is primarily intended for Silverlight where we disable the cache purposefully //Setup the Request HttpWebRequest request = (HttpWebRequest)WebRequest.Create(u); //Want to ask for RDF formats if (parser != null) { //If a non-null parser set up a HTTP Header that is just for the given parser request.Accept = MimeTypesHelper.CustomHttpAcceptHeader(parser); } else { request.Accept = MimeTypesHelper.HttpAcceptHeader; } //Use HTTP GET request.Method = "GET"; #if !SILVERLIGHT request.Timeout = Options.UriLoaderTimeout; #endif if (_userAgent != null && !_userAgent.Equals(String.Empty)) { #if PORTABLE request.Headers[HttpRequestHeader.UserAgent] = _userAgent; #else request.UserAgent = _userAgent; #endif } Tools.HttpDebugRequest(request); try { request.BeginGetResponse(result => { try { using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result)) { Tools.HttpDebugResponse(response); //Get a Parser and load the RDF if (parser == null) { //Only need to auto-detect the parser if a specific one wasn't specified parser = MimeTypesHelper.GetParser(response.ContentType); } parser.Warning += RaiseWarning; parser.Load(handler, new StreamReader(response.GetResponseStream())); //Finally can invoke the callback callback(handler, state); } } catch (WebException webEx) { if (webEx.Response != null) { Tools.HttpDebugResponse((HttpWebResponse)webEx.Response); } callback(handler, new AsyncError(new RdfParseException("A HTTP Error occurred loading the URI '" + u.AbsoluteUri + "' asynchronously, see inner exeption for details", webEx), state)); } catch (Exception ex) { callback(handler, new AsyncError(new RdfParseException("Unexpected error while loading the URI '" + u.AbsoluteUri + "' asynchronously, see inner exception for details", ex), state)); } }, null); } catch (WebException webEx) { if (webEx.Response != null) { Tools.HttpDebugResponse((HttpWebResponse)webEx.Response); } callback(handler, new AsyncError(new RdfParseException("A HTTP Error occurred loading the URI '" + u.AbsoluteUri + "' asynchronously, see inner exeption for details", webEx), state)); } catch (Exception ex) { callback(handler, new AsyncError(new RdfParseException("Unexpected error while loading the URI '" + u.AbsoluteUri + "' asynchronously, see inner exception for details", ex), state)); } } #if PORTABLE catch (FormatException uriEx) #else catch (UriFormatException uriEx) #endif { //URI Format Invalid throw new RdfParseException("Unable to load from the given URI '" + u.AbsoluteUri + "' since it's format was invalid, see inner exception for details", uriEx); } }