public static int Process(GetDocumentCommandContext context)
        {
            var assemblyName   = new AssemblyName(context.AssemblyName);
            var assembly       = Assembly.Load(assemblyName);
            var entryPointType = assembly.EntryPoint?.DeclaringType;

            if (entryPointType == null)
            {
                Reporter.WriteError(Resources.FormatMissingEntryPoint(context.AssemblyPath));
                return(2);
            }

            var services = GetServices(entryPointType, context.AssemblyPath, context.AssemblyName);

            if (services == null)
            {
                return(3);
            }

            var success = TryProcess(context, services);

            if (!success)
            {
                // As part of the aspnet/Mvc#8425 fix, return 4 here.
                return(0);
            }

            return(0);
        }
Esempio n. 2
0
        public static bool TryProcess(GetDocumentCommandContext context, IServiceProvider services)
        {
            var documentName = string.IsNullOrEmpty(context.DocumentName) ?
                               GetDocumentCommand.FallbackDocumentName :
                               context.DocumentName;
            var methodName = string.IsNullOrEmpty(context.Method) ?
                             GetDocumentCommand.FallbackMethod :
                             context.Method;
            var serviceName = string.IsNullOrEmpty(context.Service) ?
                              GetDocumentCommand.FallbackService :
                              context.Service;

            Reporter.WriteInformation(Resources.FormatUsingDocument(documentName));
            Reporter.WriteInformation(Resources.FormatUsingMethod(methodName));
            Reporter.WriteInformation(Resources.FormatUsingService(serviceName));

            try
            {
                var serviceType = Type.GetType(serviceName, throwOnError: true);
                var method      = serviceType.GetMethod(methodName, new[] { typeof(TextWriter), typeof(string) });
                var service     = services.GetRequiredService(serviceType);

                var success = true;
                using (var writer = File.CreateText(context.Output))
                {
                    if (method.ReturnType == typeof(bool))
                    {
                        success = (bool)method.Invoke(service, new object[] { writer, documentName });
                    }
                    else
                    {
                        method.Invoke(service, new object[] { writer, documentName });
                    }
                }

                if (!success)
                {
                    // As part of the aspnet/Mvc#8425 fix, make this an error unless the file already exists.
                    var message = Resources.FormatMethodInvocationFailed(methodName, serviceName, documentName);
                    Reporter.WriteWarning(message);
                }

                return(success);
            }
            catch (Exception ex)
            {
                var message = FormatException(ex);

                // As part of the aspnet/Mvc#8425 fix, make this an error unless the file already exists.
                Reporter.WriteWarning(message);

                return(false);
            }
        }
Esempio n. 3
0
        public static int Process(GetDocumentCommandContext context)
        {
            var assemblyName   = new AssemblyName(context.AssemblyName);
            var assembly       = Assembly.Load(assemblyName);
            var entryPointType = assembly.EntryPoint?.DeclaringType;

            if (entryPointType == null)
            {
                Reporter.WriteError(Resources.FormatMissingEntryPoint(context.AssemblyPath));
                return(3);
            }

            try
            {
                var serviceFactory = HostFactoryResolver.ResolveServiceProviderFactory(assembly);
                if (serviceFactory == null)
                {
                    Reporter.WriteError(Resources.FormatMethodsNotFound(
                                            HostFactoryResolver.BuildWebHost,
                                            HostFactoryResolver.CreateHostBuilder,
                                            HostFactoryResolver.CreateWebHostBuilder,
                                            entryPointType));

                    return(4);
                }

                var services = serviceFactory(Array.Empty <string>());
                if (services == null)
                {
                    Reporter.WriteError(Resources.FormatServiceProviderNotFound(
                                            typeof(IServiceProvider),
                                            HostFactoryResolver.BuildWebHost,
                                            HostFactoryResolver.CreateHostBuilder,
                                            HostFactoryResolver.CreateWebHostBuilder,
                                            entryPointType));

                    return(5);
                }

                var success = GetDocuments(context, services);
                if (!success)
                {
                    return(6);
                }
            }
            catch (Exception ex)
            {
                Reporter.WriteError(ex.ToString());
                return(7);
            }

            return(0);
        }
        public static bool TryProcess(GetDocumentCommandContext context, IServiceProvider services)
        {
            var documentName = string.IsNullOrEmpty(context.DocumentName) ?
                               GetDocumentCommand.FallbackDocumentName :
                               context.DocumentName;
            var methodName = string.IsNullOrEmpty(context.Method) ?
                             GetDocumentCommand.FallbackMethod :
                             context.Method;
            var serviceName = string.IsNullOrEmpty(context.Service) ?
                              GetDocumentCommand.FallbackService :
                              context.Service;

            Reporter.WriteInformation(Resources.FormatUsingDocument(documentName));
            Reporter.WriteInformation(Resources.FormatUsingMethod(methodName));
            Reporter.WriteInformation(Resources.FormatUsingService(serviceName));

            try
            {
                Type serviceType = null;
                foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
                {
                    serviceType = assembly.GetType(serviceName, throwOnError: false);
                    if (serviceType != null)
                    {
                        break;
                    }
                }

                // As part of the aspnet/Mvc#8425 fix, make all warnings in this method errors unless the file already
                // exists.
                if (serviceType == null)
                {
                    Reporter.WriteWarning(Resources.FormatServiceTypeNotFound(serviceName));
                    return(false);
                }

                var method = serviceType.GetMethod(methodName, new[] { typeof(string), typeof(TextWriter) });
                if (method == null)
                {
                    Reporter.WriteWarning(Resources.FormatMethodNotFound(methodName, serviceName));
                    return(false);
                }
                else if (!typeof(Task).IsAssignableFrom(method.ReturnType))
                {
                    Reporter.WriteWarning(Resources.FormatMethodReturnTypeUnsupported(
                                              methodName,
                                              serviceName,
                                              method.ReturnType,
                                              typeof(Task)));
                    return(false);
                }

                var service = services.GetService(serviceType);
                if (service == null)
                {
                    Reporter.WriteWarning(Resources.FormatServiceNotFound(serviceName));
                    return(false);
                }

                // Create the output FileStream last to avoid corrupting an existing file or writing partial data.
                var stream = new MemoryStream();
                using (var writer = new StreamWriter(stream))
                {
                    var resultTask = (Task)method.Invoke(service, new object[] { documentName, writer });
                    if (resultTask == null)
                    {
                        Reporter.WriteWarning(
                            Resources.FormatMethodReturnedNull(methodName, serviceName, nameof(Task)));
                        return(false);
                    }

                    var finishedIndex = Task.WaitAny(resultTask, Task.Delay(TimeSpan.FromMinutes(1)));
                    if (finishedIndex != 0)
                    {
                        Reporter.WriteWarning(Resources.FormatMethodTimedOut(methodName, serviceName, 1));
                        return(false);
                    }

                    writer.Flush();
                    if (stream.Length > 0L)
                    {
                        stream.Position = 0L;
                        using (var outStream = File.Create(context.OutputPath))
                        {
                            stream.CopyTo(outStream);
                            outStream.Flush();
                        }
                    }
                }

                return(true);
            }
            catch (AggregateException ex) when(ex.InnerException != null)
            {
                foreach (var innerException in ex.Flatten().InnerExceptions)
                {
                    Reporter.WriteWarning(FormatException(innerException));
                }
            }
            catch (Exception ex)
            {
                Reporter.WriteWarning(FormatException(ex));
            }

            File.Delete(context.OutputPath);

            return(false);
        }
Esempio n. 5
0
 public GetDocumentCommandWorker(GetDocumentCommandContext context)
 {
     _context  = context ?? throw new ArgumentNullException(nameof(context));
     _reporter = context.Reporter;
 }
Esempio n. 6
0
        protected override int Execute()
        {
            var thisAssembly = typeof(GetDocumentCommand).Assembly;

            var toolsDirectory     = ToolsDirectory.Value();
            var packagedAssemblies = Directory
                                     .EnumerateFiles(toolsDirectory, "*.dll")
                                     .Except(new[] { Path.GetFullPath(thisAssembly.Location) })
                                     .ToDictionary(path => Path.GetFileNameWithoutExtension(path), path => new AssemblyInfo(path));

            // Explicitly load all assemblies we need first to preserve target project as much as possible. This
            // executable is always run in the target project's context (either through location or .deps.json file).
            foreach (var keyValuePair in packagedAssemblies)
            {
                try
                {
                    keyValuePair.Value.Assembly = Assembly.Load(new AssemblyName(keyValuePair.Key));
                }
                catch
                {
                    // Ignore all failures because missing assemblies should be loadable from tools directory.
                }
            }

#if NETCOREAPP2_1
            AssemblyLoadContext.Default.Resolving += (loadContext, assemblyName) =>
            {
                var name = assemblyName.Name;
                if (!packagedAssemblies.TryGetValue(name, out var info))
                {
                    return(null);
                }

                var assemblyPath = info.Path;
                if (!File.Exists(assemblyPath))
                {
                    throw new InvalidOperationException(
                              $"Referenced assembly '{name}' was not found in '{toolsDirectory}'.");
                }

                return(loadContext.LoadFromAssemblyPath(assemblyPath));
            };
#elif NET461
            AppDomain.CurrentDomain.AssemblyResolve += (source, eventArgs) =>
            {
                var assemblyName = new AssemblyName(eventArgs.Name);
                var name         = assemblyName.Name;
                if (!packagedAssemblies.TryGetValue(name, out var info))
                {
                    return(null);
                }

                var assembly = info.Assembly;
                if (assembly != null)
                {
                    // Loaded already
                    return(assembly);
                }

                var assemblyPath = info.Path;
                if (!File.Exists(assemblyPath))
                {
                    throw new InvalidOperationException(
                              $"Referenced assembly '{name}' was not found in '{toolsDirectory}'.");
                }

                return(Assembly.LoadFile(assemblyPath));
            };
#else
#error Target frameworks need to be updated.
#endif

            // Now safe to reference the application's code.
            try
            {
                var assemblyPath = AssemblyPath.Value();
                var context      = new GetDocumentCommandContext
                {
                    AssemblyPath    = assemblyPath,
                    AssemblyName    = Path.GetFileNameWithoutExtension(assemblyPath),
                    FileListPath    = _fileListPath.Value(),
                    OutputDirectory = _output.Value(),
                    ProjectName     = ProjectName.Value(),
                };

                return(GetDocumentCommandWorker.Process(context));
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.ToString());
                return(2);
            }
        }
Esempio n. 7
0
        private static bool GetDocuments(GetDocumentCommandContext context, IServiceProvider services)
        {
            Type serviceType = null;

            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                serviceType = assembly.GetType(DocumentService, throwOnError: false);
                if (serviceType != null)
                {
                    break;
                }
            }

            if (serviceType == null)
            {
                Reporter.WriteError(Resources.FormatServiceTypeNotFound(DocumentService));
                return(false);
            }

            var getDocumentsMethod = GetMethod(
                GetDocumentsMethodName,
                serviceType,
                GetDocumentsParameterTypes,
                GetDocumentsReturnType);

            if (getDocumentsMethod == null)
            {
                return(false);
            }

            var generateMethod = GetMethod(
                GenerateMethodName,
                serviceType,
                GenerateMethodParameterTypes,
                GenerateMethodReturnType);

            if (generateMethod == null)
            {
                return(false);
            }

            var service = services.GetService(serviceType);

            if (service == null)
            {
                Reporter.WriteError(Resources.FormatServiceNotFound(DocumentService));
                return(false);
            }

            var documentNames = (IEnumerable <string>)InvokeMethod(getDocumentsMethod, service, GetDocumentsArguments);

            if (documentNames == null)
            {
                return(false);
            }

            // Write out the documents.
            Directory.CreateDirectory(context.OutputDirectory);
            var filePathList = new List <string>();

            foreach (var documentName in documentNames)
            {
                var filePath = GetDocument(
                    documentName,
                    context.ProjectName,
                    context.OutputDirectory,
                    generateMethod,
                    service);
                if (filePath == null)
                {
                    return(false);
                }

                filePathList.Add(filePath);
            }

            // Write out the cache file.
            var stream = File.Create(context.FileListPath);

            using var writer = new StreamWriter(stream);
            writer.WriteLine(string.Join(Environment.NewLine, filePathList));

            return(true);
        }