/// <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> /// </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 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); } //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 !SILVERLIGHT request.Timeout = Options.UriLoaderTimeout; #endif if (_userAgent != null && !_userAgent.Equals(String.Empty)) { request.UserAgent = _userAgent; } #if DEBUG //HTTP Debugging if (Options.HttpDebugging) { Tools.HttpDebugRequest(request); } #endif request.BeginGetResponse(result => { using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result)) { #if DEBUG if (Options.HttpDebugging) { Tools.HttpDebugResponse(response); } #endif //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 StreamParams(response.GetResponseStream())); } catch (RdfParserSelectionException selEx) { String data = new StreamReader(response.GetResponseStream()).ReadToEnd(); parser = StringParser.GetDatasetParser(data); parser.Warning += RaiseStoreWarning; parser.Load(handler, new TextReaderParams(new StringReader(data))); } } else { parser.Warning += RaiseStoreWarning; parser.Load(handler, new StreamParams(response.GetResponseStream())); } //Finally can invoke the callback callback(handler, state); } }, null); } catch (UriFormatException uriEx) { //Uri Format Invalid throw new RdfException("Unable to load from the given URI '" + u.ToString() + "' since it's format was invalid, see inner exception for details", uriEx); } catch (WebException webEx) { #if DEBUG if (Options.HttpDebugging) { if (webEx.Response != null) { Tools.HttpDebugResponse((HttpWebResponse)webEx.Response); } } #endif //Some sort of HTTP Error occurred throw new WebException("A HTTP Error occurred resolving the URI '" + u.ToString() + "', see innner exception for details", webEx); } }
/// <summary> /// Loads RDF data using an RDF Handler from a data: URI /// </summary> /// <param name="handler">RDF Handler</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(IRdfHandler handler, Uri u) { if (u == null) { throw new RdfParseException("Cannot load RDF from a null URI"); } if (handler == null) { throw new RdfParseException("Cannot read RDF into a null RDF Handler"); } if (!u.Scheme.Equals("data")) { //Invoke the normal URI Loader if not a data: URI #if !SILVERLIGHT UriLoader.Load(handler, u); #else UriLoader.Load(handler, u, (_, _1) => { }, null); #endif return; } String mimetype = "text/plain"; bool mimeSet = false; bool base64 = false; String[] uri = u.AbsolutePath.Split(','); String metadata = uri[0]; String data = uri[1]; //Process the metadata if (metadata.Equals(String.Empty)) { //Nothing to do } else if (metadata.Contains(';')) { if (metadata.StartsWith(";")) { metadata = metadata.Substring(1); } String[] meta = metadata.Split(';'); for (int i = 0; i < meta.Length; i++) { if (meta[i].StartsWith("charset=")) { //OPT: Do we need to process the charset parameter here at all? //String charset = meta[i].Substring(meta[i].IndexOf('=') + 1); } else if (meta[i].Equals("base64")) { base64 = true; } else if (meta[i].Contains('/')) { mimetype = meta[i]; mimeSet = true; } else { throw new UriFormatException("This data: URI appears to be malformed as encountered the parameter value '" + meta[i] + "' in the metadata section of the URI"); } } } else { if (metadata.StartsWith("charset=")) { //OPT: Do we need to process the charset parameter here at all? } else if (metadata.Equals(";base64")) { base64 = true; } else if (metadata.Contains('/')) { mimetype = metadata; mimeSet = true; } else { throw new UriFormatException("This data: URI appears to be malformed as encountered the parameter value '" + metadata + "' in the metadata section of the URI"); } } //Process the data if (base64) { StringWriter temp = new StringWriter(); foreach (byte b in Convert.FromBase64String(data)) { temp.Write((char)((int)b)); } data = temp.ToString(); } else { data = Uri.UnescapeDataString(data); } //Now either select a parser based on the MIME type or let StringParser guess the format try { if (mimeSet) { //If the MIME Type was explicitly set then we'll try and get a parser and use it IRdfReader reader = MimeTypesHelper.GetParser(mimetype); reader.Load(handler, new StringReader(data)); } else { //If the MIME Type was not explicitly set we'll let the StringParser guess the format IRdfReader reader = StringParser.GetParser(data); reader.Load(handler, new StringReader(data)); } } catch (RdfParserSelectionException) { //If we fail to get a parser then we'll let the StringParser guess the format IRdfReader reader = StringParser.GetParser(data); reader.Load(handler, new StringReader(data)); } }