private async Task <Document> LoadDocumentAsync(DocumentSettings settings, Uri uri, DocumentCategory category, DocumentContextCallback contextCallback) { var cachedDocument = GetCachedDocument(uri); if (cachedDocument != null) { return(cachedDocument); } string contents; var flags = settings.AccessFlags; if (uri.IsFile) { if (!flags.HasFlag(DocumentAccessFlags.EnableFileLoading)) { throw new UnauthorizedAccessException("This script engine is not configured for loading documents from the file system"); } using (var reader = new StreamReader(uri.LocalPath)) { contents = await reader.ReadToEndAsync().ConfigureAwait(false); } } else { if (!flags.HasFlag(DocumentAccessFlags.EnableWebLoading)) { throw new UnauthorizedAccessException("This script engine is not configured for downloading documents from the Web"); } using (var client = new WebClient()) { contents = await client.DownloadStringTaskAsync(uri).ConfigureAwait(false); } } var documentInfo = new DocumentInfo(uri) { Category = category, ContextCallback = contextCallback }; var callback = settings.LoadCallback; if (callback != null) { callback(ref documentInfo); } return(CacheDocument(new StringDocument(documentInfo, contents))); }
private static IEnumerable <Uri> GetRawUris(DocumentSettings settings, DocumentInfo?sourceInfo, string specifier) { Uri baseUri; Uri uri; string path; if (sourceInfo.HasValue && SpecifierMayBeRelative(settings, specifier)) { baseUri = GetBaseUri(sourceInfo.Value); if ((baseUri != null) && Uri.TryCreate(baseUri, specifier, out uri)) { yield return(uri); } } var searchPath = settings.SearchPath; if (!string.IsNullOrWhiteSpace(searchPath)) { foreach (var url in searchPath.SplitSearchPath()) { if (Uri.TryCreate(url, UriKind.Absolute, out baseUri) && TryCombineSearchUri(baseUri, specifier, out uri)) { yield return(uri); } } } if (MiscHelpers.Try(out path, () => Path.Combine(Directory.GetCurrentDirectory(), specifier)) && Uri.TryCreate(path, UriKind.Absolute, out uri)) { yield return(uri); } if (MiscHelpers.Try(out path, () => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, specifier)) && Uri.TryCreate(path, UriKind.Absolute, out uri)) { yield return(uri); } using (var process = Process.GetCurrentProcess()) { var module = process.MainModule; if ((module != null) && Uri.TryCreate(module.FileName, UriKind.Absolute, out baseUri) && Uri.TryCreate(baseUri, specifier, out uri)) { yield return(uri); } } }
/// <summary> /// Loads a document. /// </summary> /// <param name="settings">Document access settings for the operation.</param> /// <param name="sourceInfo">An optional structure containing meta-information for the requesting document.</param> /// <param name="specifier">A string specifying the document to be loaded.</param> /// <param name="category">An optional category for the requested document.</param> /// <param name="contextCallback">An optional context callback for the requested document.</param> /// <returns>A <see cref="Document"/> instance that represents the loaded document.</returns> /// <remarks> /// A loaded document must have an absolute <see cref="DocumentInfo.Uri">URI</see>. Once a /// load operation has completed successfully, subsequent requests that resolve to the same /// URI are expected to return the same <see cref="Document"/> reference, although loaders /// are not required to manage document caches of unlimited size. /// </remarks> public virtual Document LoadDocument(DocumentSettings settings, DocumentInfo?sourceInfo, string specifier, DocumentCategory category, DocumentContextCallback contextCallback) { MiscHelpers.VerifyNonBlankArgument(specifier, "specifier", "Invalid document specifier"); try { return(LoadDocumentAsync(settings, sourceInfo, specifier, category, contextCallback).Result); } catch (AggregateException exception) { exception = exception.Flatten(); if (exception.InnerExceptions.Count == 1) { throw new FileLoadException(null, specifier, exception.InnerExceptions[0]); } throw new FileLoadException(null, specifier, exception); } }
private static async Task <List <Uri> > GetCandidateUrisAsync(DocumentSettings settings, DocumentInfo?sourceInfo, string specifier) { var candidateUris = new List <Uri>(); var rawUris = GetRawUris(settings, sourceInfo, specifier).Distinct(); if (!string.IsNullOrWhiteSpace(settings.FileNameExtensions)) { rawUris = rawUris.SelectMany(uri => ApplyFileNameExtensions(sourceInfo, uri, settings.FileNameExtensions)); } foreach (var testUri in rawUris) { if (await IsCandidateUriAsync(settings, testUri).ConfigureAwait(false)) { candidateUris.Add(testUri); } } return(candidateUris); }
private static async Task <List <Uri> > GetCandidateUrisAsync(DocumentSettings settings, DocumentInfo?sourceInfo, Uri uri) { var candidateUris = new List <Uri>(); if (string.IsNullOrWhiteSpace(settings.FileNameExtensions)) { candidateUris.Add(uri); } else { foreach (var testUri in ApplyFileNameExtensions(sourceInfo, uri, settings.FileNameExtensions)) { if (await IsCandidateUriAsync(settings, testUri).ConfigureAwait(false)) { candidateUris.Add(testUri); } } } return(candidateUris); }
/// <summary> /// Loads a document asynchronously. /// </summary> /// <param name="settings">Document access settings for the operation.</param> /// <param name="sourceInfo">An optional structure containing meta-information for the requesting document.</param> /// <param name="specifier">A string specifying the document to be loaded.</param> /// <param name="category">An optional category for the requested document.</param> /// <param name="contextCallback">An optional context callback for the requested document.</param> /// <returns>A task that represents the asynchronous operation. Upon completion, the task's result is a <see cref="Document"/> instance that represents the loaded document.</returns> /// <remarks> /// A loaded document must have an absolute <see cref="DocumentInfo.Uri">URI</see>. Once a /// load operation has completed successfully, subsequent requests that resolve to the same /// URI are expected to return the same <see cref="Document"/> reference, although loaders /// are not required to manage document caches of unlimited size. /// </remarks> public abstract Task <Document> LoadDocumentAsync(DocumentSettings settings, DocumentInfo?sourceInfo, string specifier, DocumentCategory category, DocumentContextCallback contextCallback);
public override async Task <Document> LoadDocumentAsync(DocumentSettings settings, DocumentInfo?sourceInfo, string specifier, DocumentCategory category, DocumentContextCallback contextCallback) { MiscHelpers.VerifyNonNullArgument(settings, "settings"); MiscHelpers.VerifyNonBlankArgument(specifier, "specifier", "Invalid document specifier"); if ((settings.AccessFlags & DocumentAccessFlags.EnableAllLoading) == DocumentAccessFlags.None) { throw new UnauthorizedAccessException("This script engine is not configured for loading documents"); } if (category == null) { category = sourceInfo.HasValue ? sourceInfo.Value.Category : DocumentCategory.Script; } List <Uri> candidateUris; Uri uri; if (Uri.TryCreate(specifier, UriKind.RelativeOrAbsolute, out uri) && uri.IsAbsoluteUri) { candidateUris = await GetCandidateUrisAsync(settings, sourceInfo, uri).ConfigureAwait(false); } else { candidateUris = await GetCandidateUrisAsync(settings, sourceInfo, specifier).ConfigureAwait(false); } if (candidateUris.Count < 1) { throw new FileNotFoundException(null, specifier); } if (candidateUris.Count == 1) { return(await LoadDocumentAsync(settings, candidateUris[0], category, contextCallback).ConfigureAwait(false)); } var exceptions = new List <Exception>(candidateUris.Count); foreach (var candidateUri in candidateUris) { var task = LoadDocumentAsync(settings, candidateUri, category, contextCallback); try { return(await task.ConfigureAwait(false)); } catch (Exception exception) { if ((task.Exception != null) && task.Exception.InnerExceptions.Count == 1) { Debug.Assert(ReferenceEquals(task.Exception.InnerExceptions[0], exception)); exceptions.Add(exception); } else { exceptions.Add(task.Exception); } } } if (exceptions.Count < 1) { MiscHelpers.AssertUnreachable(); throw new FileNotFoundException(null, specifier); } if (exceptions.Count == 1) { MiscHelpers.AssertUnreachable(); throw new FileLoadException(exceptions[0].Message, specifier, exceptions[0]); } throw new AggregateException(exceptions).Flatten(); }
private static async Task <bool> IsCandidateUriAsync(DocumentSettings settings, Uri uri) { return(uri.IsFile ? settings.AccessFlags.HasFlag(DocumentAccessFlags.EnableFileLoading) && File.Exists(uri.LocalPath) : settings.AccessFlags.HasFlag(DocumentAccessFlags.EnableWebLoading) && await WebDocumentExistsAsync(uri).ConfigureAwait(false)); }
private static bool SpecifierMayBeRelative(DocumentSettings settings, string specifier) { return(!settings.AccessFlags.HasFlag(DocumentAccessFlags.EnforceRelativePrefix) || relativePrefixes.Any(specifier.StartsWith)); }