コード例 #1
0
        protected override void ProcessQueueEntries(List <ExceptionWrapper> entryCollection)
        {
            try
            {
                DateTime?lastFailedToLogToStoreDate = null;

                foreach (var ew in entryCollection)
                {
                    try
                    {
                        AddExceptionToDB(ew);
                    }
                    catch (Exception ee)
                    {
                        // prevent logging failures too often
                        if (!lastFailedToLogToStoreDate.HasValue || DateTime.Now.Subtract(lastFailedToLogToStoreDate.Value).TotalSeconds >= 25)
                        {
                            Log.Error(ee, $"Failed to log exception to DB store. EP={ew.EndpointKey}; sID={ew.sId};");
                            Log.Error($"Original: {ew.message}; stack=\r\n{ew.stackTrace}");

                            lastFailedToLogToStoreDate = DateTime.Now;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "ExceptionLogger::ProcessMessagesLoop failed");
                SessionLog.Error("ExceptionLogger::ProcessMessagesLoop failed");
                SessionLog.Exception(ex);
            }
        }
コード例 #2
0
        public void Init()
        {
            try
            {
                if (File.Exists(InlinePluginManifestPath))
                {
                    var json = File.ReadAllText(InlinePluginManifestPath);

                    if (!string.IsNullOrWhiteSpace(json))
                    {
                        var entries = JsonConvert.DeserializeObject <InlineModuleManifestEntry[]>(json);

                        _entries = new List <InlineModuleManifestEntry>(entries);
                        Entries  = _entries.AsReadOnly();
                    }
                    else
                    {
                        _entries = new List <InlineModuleManifestEntry>();
                        Entries  = _entries.AsReadOnly();
                    }
                }
                else
                {
                    _entries = new List <InlineModuleManifestEntry>();
                    Entries  = _entries.AsReadOnly();
                }
            }
            catch (Exception ex)
            {
                ExceptionLogger.LogException(ex);
                SessionLog.Exception(ex);
            }
        }
コード例 #3
0
        public static bool ValidateUrlAcl(bool isHttps, string hostname, int port)
        {
            try
            {
                var url = $"http{(isHttps ? "s" : "")}://{hostname}:{port}".ToLower();
                var acl = ShowUrlAcl(isHttps, hostname, port);

                var lines = acl.Split("\r\n", StringSplitOptions.RemoveEmptyEntries);

                var l = lines.FirstOrDefault(ln => ln.ToLower().Contains("reserved url"));

                if (l != null)
                {
                    return(l.ToLower().Contains(url));
                }
                else
                {
                    return(false);
                }
            }
            catch (Exception ex)
            {
                SessionLog.Exception(ex);
                return(false);
            }
        }
コード例 #4
0
        public CommonReturnValue GetInlinePluginModuleSource(string inlineEntryId, out InlineModuleManifestEntry existingInlineEntry, out string source)
        {
            source = null;
            existingInlineEntry = null;

            var pluginAssembly = this.PluginAssemblies.FirstOrDefault(p => p.InlineEntryId != null && p.InlineEntryId.Equals(inlineEntryId, StringComparison.Ordinal) && p.IsInline);

            if (pluginAssembly == null)
            {
                return(CommonReturnValue.UserError($"An inline module with the Id '{inlineEntryId}' does not exist"));
            }

            try
            {
                existingInlineEntry = InlineModuleManifest.Instance.GetEntryById(pluginAssembly.InlineEntryId);
                var sourcePath = System.IO.Path.Combine(InlinePluginSourcePath, existingInlineEntry.Id);

                if (System.IO.File.Exists(sourcePath))
                {
                    source = System.IO.File.ReadAllText(sourcePath);
                    return(CommonReturnValue.Success());
                }
                else
                {
                    return(CommonReturnValue.UserError($"Failed to find source at: {sourcePath}"));
                }
            }
            catch (Exception e)
            {
                SessionLog.Warning("Failed to fetch file of plugin module with InstanceId = {0}; {1}", pluginAssembly.InstanceId, pluginAssembly.Assembly.FullName);
                SessionLog.Exception(e);
            }

            return(CommonReturnValue.Success());
        }
コード例 #5
0
        public static bool ValidateSSLCertBinding(string hostname, int port)
        {
            try
            {
                var output = ShowSslCert(hostname, port);

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

                output = output.ToLower();

                if (output.Contains("the system cannot find the file specified"))
                {
                    return(false);
                }

                return(true);
            }
            catch (Exception ex)
            {
                SessionLog.Exception(ex);
                return(false);
            }
        }
コード例 #6
0
        public static ApiResponseServerMethodBase Exception(Exception ex)
        {
            SessionLog.Exception(ex);

            // TODO: Record ServerMethod detail
            var id = ExceptionLogger.LogException(ex, (Controllers.ExecController.ExecOptions)null);

            var ret = new ApiResponseServerMethodBase();

            ret.Error = $"Error ref: {id}";
            ret.Type  = ApiResponseType.Exception;

            return(ret);
        }
コード例 #7
0
        public static void Start()
        {
            try
            {
                var endpoints = SettingsInstance.Instance.ProjectList.SelectMany(p => p.Applications).SelectMany(app => app.Endpoints).ToList();

                WorkSpawner.TEMPLATE_RoutineContainer      = File.ReadAllText("./resources/RoutineContainerTemplate.txt");
                WorkSpawner.TEMPLATE_Routine               = File.ReadAllText("./resources/RoutineTemplate.txt");
                WorkSpawner.TEMPLATE_TypescriptDefinitions = File.ReadAllText("./resources/TypeScriptDefinitionsContainer.d.ts");

                WorkSpawner._workerList = new List <Worker>();

                //dbSources = new DatabaseSource[] { dbSources.First() }.ToList(); //TEMP

                // TODO: handle items (project/sources) that were deleted


                //async.each(dbSources, (source) => {
                endpoints.ForEach(endpoint =>
                {
                    //TEST!!
                    //   if (endpoint.Name != "DEV" || endpoint.Application.Name != "PWAs") return;

                    try
                    {
                        CreateNewWorker(endpoint);
                    }
                    catch (Exception e)
                    {
                        Log.Error(e, $"Failed to create new work for {endpoint.Pedigree}");
                        ExceptionLogger.LogException(e);
                    }
                });

                Hubs.WorkerMonitor.Instance.NotifyObservers();
            }
            catch (Exception e)
            {
                SessionLog.Exception(e);
                Log.Error(e, "Work spawner error on start");
            }
        } // Start
コード例 #8
0
        public void AddPlugin(PluginInfo plugin)
        {
            try
            {
                this._plugins.Add(plugin);

                if (plugin.Type == PluginType.BackgroundThread)
                {
                    BackgroundThreadPluginManager.Instance.Register(plugin);
                }
                else if (plugin.Type == PluginType.ServerMethod)
                {
                    ServerMethodManager.Register(InstanceId, plugin);
                }
            }
            catch (Exception ex)
            {
                SessionLog.Exception(ex);
            }
        }
コード例 #9
0
        public override void Init()
        {
            try
            {
                _throttleTracker = new Dictionary <string, List <DateTime> >();

                _database = new LiteDB.LiteDatabase("data/exceptions.db");

                var exceptionCollection = _database.GetCollection <ExceptionWrapper>("Exceptions");

                exceptionCollection.EnsureIndex("sId", unique: true);
                exceptionCollection.EnsureIndex("EndpointKey", unique: false);

                base.Init();
            }
            catch (Exception ex)
            {
                SessionLog.Exception(ex);
                Log.Error(ex, "Failed to initiate Exceptions DB");
            }
        }
コード例 #10
0
        public static void RemoveEndpoint(Endpoint endpoint)
        {
            try
            {
                lock (_workerList)
                {
                    var worker = GetWorkerByEndpoint(endpoint);

                    if (worker != null)
                    {
                        worker.Stop();
                        _workerList.Remove(worker);
                        Hubs.WorkerMonitor.Instance.NotifyObservers();
                    }
                }
            }
            catch (Exception ex)
            {
                SessionLog.Exception(ex);
            }
        }
コード例 #11
0
        private static PluginSetParameterValue GetParameterValueFromPlugins(CachedRoutine routine, string parameterName, List <ExecutionPlugin> plugins)
        {
            foreach (var plugin in plugins)
            {
                try
                {
                    var val = plugin.GetParameterValue(routine.Schema, routine.Routine, parameterName);

                    if (val != PluginSetParameterValue.DontSet)
                    {
                        return(val);
                    }
                }
                catch (Exception ex)
                {
                    SessionLog.Error("Plugin {0} GetParameterValue failed", plugin.Name);
                    SessionLog.Exception(ex);
                }
            }

            return(PluginSetParameterValue.DontSet);
        }
コード例 #12
0
ファイル: worker.cs プロジェクト: pietie/jsdal-server-core
        private (List <ResultSetFieldMetadata>, string) ExtractResultSetMetadata(string resultSetXml)
        {
            try
            {
                var xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(SqlResultSetFieldCollection));

                resultSetXml = $"<FieldCollection>{resultSetXml}</FieldCollection>";

                using (var sr = new StringReader(resultSetXml))
                {
                    var val = (xmlSerializer.Deserialize(sr) as Settings.ObjectModel.SqlResultSetFieldCollection);

                    // look for error
                    if (val.Fields.Count > 0 && !string.IsNullOrWhiteSpace(val.Fields[0].ErrorMsg))
                    {
                        var f = val.Fields[0];
                        return(null, $"({f.ErrorDescription}) {f.ErrorMsg}");
                    }
                    else
                    {
                        return(val.Fields.Select(f => new ResultSetFieldMetadata()
                        {
                            ColumnName = f.Name,
                            DataType = RoutineParameterV2.GetCSharpDataTypeFromSqlDbType(f.Type),
                            DbDataType = f.Type,
                            ColumnSize = f.Size,
                            NumericalPrecision = f.Precision,
                            NumericalScale = f.Scale
                        }).ToList(), null);
                    }
                }
            }
            catch (Exception ex)
            {
                SessionLog.Exception(ex);
                return(null, "Failed to parse ResultSetXml:" + ex.Message);
            }
        }
コード例 #13
0
        private void CompileCodeIntoAssemblyContext(InlineModuleManifestEntry inlineEntry, string code)
        {
            var ctxName    = $"Inline Plugin Context {++_asmCtxCounter}";
            var pluginPath = Path.GetFullPath("plugins");
            var asmCtx     = new PluginAssemblyLoadContext(pluginPath, ctxName, true /*enable unloading*/);

            ASM_CTXES.Add(asmCtx);

            SessionLog.Info($"Created {ctxName} for {inlineEntry.Name}".PadRight(35));

            var assemblyBytes = CSharpCompilerHelper.CompileIntoAssembly(inlineEntry.Name, code, out var problems);

            if ((problems != null && problems.Count == 0))
            {
                Assembly assembly = null;

                try
                {
                    using (var ms = new MemoryStream(assemblyBytes))
                    {
                        assembly = asmCtx.LoadFromStream(ms);

                        ParseAndLoadPluginAssembly(asmCtx, assembly, inlineEntry.Id);
                    }
                }
                catch (Exception ee)
                {
                    SessionLog.Error($"Failed to load inline plugin assembly '{assembly?.FullName}' {inlineEntry.Name}/{inlineEntry.Id}. See exception that follows.");
                    SessionLog.Exception(ee);
                }
            }
            else
            {
                SessionLog.Error($"Inline plugin {inlineEntry.Name} ({inlineEntry.Id}) failed to compile with the following error(s): {string.Join(", ", problems)}");
            }
        }
コード例 #14
0
        public static IWebHostBuilder BuildWebHost(string pathToContentRoot, string[] args)
        {
            var webServerSettings = SettingsInstance.Instance.Settings.WebServer;

            // var certPath = "cert.pfx";
            // var certPassPath = Path.GetFullPath("cert.pass");

            // if (!File.Exists(certPassPath))
            // {
            //     throw new Exception($"Unable to find cert path file: {certPassPath}");
            // }

            // var certPass = System.IO.File.ReadAllText(certPassPath);


            //                 var configurationBuilder = new ConfigurationBuilder();

            //                 configurationBuilder.AddJsonFile("./appsettings.json", false, true);

            // var appConfig = configurationBuilder.Build();


            return(WebHost
                   .CreateDefaultBuilder(args)
                   .UseSerilog()
                   .UseContentRoot(pathToContentRoot)
                   .UseWebRoot(Path.Combine(pathToContentRoot, "wwwroot"))
                   .UseSetting(WebHostDefaults.SuppressStatusMessagesKey, "true")
                   //   .ConfigureAppConfiguration((builderContext, config) =>
                   //   {
                   //     IHostingEnvironment env = builderContext.HostingEnvironment;

                   //     config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
                   //         //.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
                   //   })

                   .UseHttpSys(options =>
            {
                options.Authentication.Schemes = AuthenticationSchemes.None;
                options.Authentication.AllowAnonymous = true;
                options.MaxConnections = null;
                options.MaxRequestBodySize = 30000000;       //~30MB

                int interfaceCnt = 0;

                if ((webServerSettings.EnableSSL ?? false) &&
                    !string.IsNullOrWhiteSpace(webServerSettings.HttpsServerHostname) &&
                    webServerSettings.HttpsServerPort.HasValue &&
                    !string.IsNullOrWhiteSpace(webServerSettings.HttpsCertHash))
                {
                    try
                    {
                        var httpsUrl = $"https://{webServerSettings.HttpsServerHostname}:{webServerSettings.HttpsServerPort.Value}";

                        if (NetshWrapper.ValidateSSLCertBinding(webServerSettings.HttpsServerHostname, webServerSettings.HttpsServerPort.Value))
                        {
                            if (NetshWrapper.ValidateUrlAcl(true, webServerSettings.HttpsServerHostname, webServerSettings.HttpsServerPort.Value))
                            {
                                //!eventLog.Info($"Listening to {httpsUrl}");
                                options.UrlPrefixes.Add(httpsUrl);
                                interfaceCnt++;
                            }
                            else
                            {
                                if (NetshWrapper.AddUrlToACL(true, webServerSettings.HttpsServerHostname, webServerSettings.HttpsServerPort.Value))
                                {
                                    //!eventLog.Info($"Listening to {httpsUrl}");
                                    options.UrlPrefixes.Add(httpsUrl);
                                    interfaceCnt++;
                                }
                                else
                                {
                                    SessionLog.Error($"The url '{httpsUrl}' was not found in ACL list so a listener for this URL cannot be started.");
                                    Log.Error($"The url '{httpsUrl}' was not found in ACL list so a listener for this URL cannot be started.");
                                }
                            }
                        }
                        else
                        {
                            SessionLog.Error($"There is no SSL cert binding for '{httpsUrl}' so a listener for this URL cannot be started.");
                            Log.Error($"There is no SSL cert binding for '{httpsUrl}' so a listener for this URL cannot be started.");
                        }
                    }
                    catch (Exception ex)
                    {
                        SessionLog.Exception(ex);
                        Log.Error(ex, "HTTPS init failed");
                    }
                }

                if (webServerSettings.EnableBasicHttp ?? false)
                {
                    try
                    {
                        var httpUrl = $"http://{webServerSettings.HttpServerHostname}:{webServerSettings.HttpServerPort}";

                        if (NetshWrapper.ValidateUrlAcl(false, webServerSettings.HttpServerHostname, webServerSettings.HttpServerPort.Value))
                        {
                            //!eventLog.Info($"Listening to {httpUrl}");
                            options.UrlPrefixes.Add(httpUrl);
                            interfaceCnt++;
                        }
                        else
                        {
                            if (NetshWrapper.AddUrlToACL(false, webServerSettings.HttpServerHostname, webServerSettings.HttpServerPort.Value))
                            {
                                //!eventLog.Info($"Listening to {httpUrl}");
                                options.UrlPrefixes.Add(httpUrl);
                                interfaceCnt++;
                            }
                            else
                            {
                                SessionLog.Error($"The url '{httpUrl}' was not found in ACL list so a listener for this URL cannot be started.");
                                Log.Error($"The url '{httpUrl}' was not found in ACL list so a listener for this URL cannot be started.");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        SessionLog.Exception(ex);
                        Log.Error(ex, "Basic Http init failed");
                    }
                }

                if (interfaceCnt == 0)
                {
                    Log.Warning("No valid interface (http or https) found so defaulting to localhost:9086");
                    options.UrlPrefixes.Add("http://localhost:9086");
                }
            })
                   //   .UseKestrel(options =>
                   //   {
                   //       options.AddServerHeader = false;

                   //       // TODO: Allow more config here, especially the limits
                   //       //!options.Limits.MaxConcurrentConnections


                   //       if (webServerSettings.EnableSSL ?? false)
                   //       {

                   //           if (File.Exists(certPath))
                   //           {
                   //               options.Listen(System.Net.IPAddress.Any, webServerSettings.HttpsServerPort ?? 44312, listenOptions =>
                   //               {
                   //                   try
                   //                   {
                   //                       listenOptions.UseHttps(certPath, certPass);
                   //                   }
                   //                   catch (System.Exception ex)
                   //                   {
                   //                       SessionLog.Exception(ex);
                   //                       Cons ole.WriteLine(ex.ToString());
                   //                       throw;
                   //                   }
                   //               });
                   //           }
                   //           else
                   //           {
                   //               Cons ole.WriteLine("Cannot start HTTPS listener: The cert file '{0}' does not exists.", certPath);
                   //           }
                   //       }

                   //       if (webServerSettings.EnableBasicHttp ?? false)
                   //       {
                   //           options.Listen(System.Net.IPAddress.Any, webServerSettings.HttpServerPort ?? 9086); // http
                   //       }

                   //   })
                   .UseStartup <Startup>()
                   .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")

                   );
            //     .UseUrls("http://localhost:9086", "https://*:4430")
        }
コード例 #15
0
        public static void GenerateJsFileV2(string source, Endpoint endpoint, JsFile jsFile, Dictionary <string, ChangeDescriptor> fullChangeSet = null, bool rulesChanged = false)
        {
            var generateMetric = new Performance.ExecutionBase("GenerateJsFileV2");
            var noChanges      = false;

            try
            {
                // TODO: Figure out out casing on this property
                string jsNamespace = null;//endpoint.JsNamespace;
                if (string.IsNullOrWhiteSpace(jsNamespace))
                {
                    jsNamespace = endpoint.MetadataConnection.InitialCatalog;
                }

                var jsSafeNamespace = MakeNameJsSafe(jsNamespace);

                var routineContainerTemplate       = WorkSpawner.TEMPLATE_RoutineContainer;
                var routineTemplate                = WorkSpawner.TEMPLATE_Routine;
                var typescriptDefinitionsContainer = WorkSpawner.TEMPLATE_TypescriptDefinitions;

                endpoint.ApplyRules(jsFile);

                var includedRoutines = (from row in endpoint.CachedRoutines
                                        where !row.IsDeleted && (row.RuleInstructions[jsFile]?.Included ?? false == true)
                                        orderby row.FullName
                                        select row).ToList();

                List <KeyValuePair <string, ChangeDescriptor> > changesInFile = null;


                if (fullChangeSet != null)
                {
                    changesInFile = fullChangeSet.Where(change => includedRoutines.Count(inc => inc.FullName.Equals(change.Key, StringComparison.OrdinalIgnoreCase)) > 0).ToList();

                    // TODO: Consider if this is a good idea?
                    //       If we can reasonably say that there are no changes to routines that this JsFile cares about, why regenerate this file and why give it a new Version
                    if (changesInFile.Count == 0)
                    {
                        noChanges = true;
                        return;
                    }
                }

                var jsSchemaLookupForJsFunctions = new Dictionary <string, List <string> /*Routine defs*/>();
                var tsSchemaLookup = new Dictionary <string, List <string> /*Routine defs*/>();

                var typeScriptParameterAndResultTypesSB = new StringBuilder();

                var serverMethodPlugins = PluginLoader.Instance.PluginAssemblies
                                          .SelectMany(pa => pa.Plugins)
                                          .Where(p => p.Type == PluginType.ServerMethod && endpoint.Application.IsPluginIncluded(p.Guid.ToString()));

                var uniqueSchemas = new List <string>();

                var mainLoopMetric = generateMetric.BeginChildStage("Main loop");

                includedRoutines.ForEach(r =>
                {
                    try
                    {
                        if (r.TypescriptMethodStub == null)
                        {
                            r.PrecalculateJsGenerationValues(endpoint);
                        }

                        var jsSchemaName   = JsFileGenerator.MakeNameJsSafe(r.Schema);
                        var jsFunctionName = JsFileGenerator.MakeNameJsSafe(r.Routine);

                        if (!jsSchemaLookupForJsFunctions.ContainsKey(jsSchemaName))
                        {
                            jsSchemaLookupForJsFunctions.Add(jsSchemaName, new List <string>());
                        }

                        if (!tsSchemaLookup.ContainsKey(jsSchemaName))
                        {
                            tsSchemaLookup.Add(jsSchemaName, new List <string>());
                        }

                        if (!uniqueSchemas.Contains(r.Schema))
                        {
                            uniqueSchemas.Add(r.Schema);
                        }

                        var schemaIx = uniqueSchemas.IndexOf(r.Schema);

                        // .js
                        {
                            var jsFunctionDefLine = routineTemplate.Replace("<<FUNC_NAME>>", jsFunctionName).Replace("<<SCHEMA_IX>>", schemaIx.ToString()).Replace("<<ROUTINE>>", r.Routine);

                            if (r.Type.Equals(string.Intern("PROCEDURE"), StringComparison.OrdinalIgnoreCase))
                            {
                                jsFunctionDefLine = jsFunctionDefLine.Replace("<<CLASS>>", "S");
                            }
                            else
                            {
                                jsFunctionDefLine = jsFunctionDefLine.Replace("<<CLASS>>", "U");
                            }

                            jsSchemaLookupForJsFunctions[jsSchemaName].Add(jsFunctionDefLine);
                        }

                        // .tsd
                        {
                            typeScriptParameterAndResultTypesSB.AppendLine(r.TypescriptParameterTypeDefinition);
                            typeScriptParameterAndResultTypesSB.AppendLine(r.TypescriptOutputParameterTypeDefinition);
                            typeScriptParameterAndResultTypesSB.AppendLine(r.TypescriptResultSetDefinitions);
                            tsSchemaLookup[jsSchemaName].Add(r.TypescriptMethodStub);
                        }
                    }
                    catch (Exception ex)
                    {
                        SessionLog.Exception(ex);
                        // TODO: quit whole process
                    }
                });

                mainLoopMetric.End();

                var finalSBMetric = generateMetric.BeginChildStage("Final SB");

                var schemaAndRoutineDefs   = string.Join("\r\n", jsSchemaLookupForJsFunctions.Select(s => "\tx." + s.Key + " = {\r\n\t\t" + string.Join(",\r\n\t\t", s.Value.ToArray()) + "\r\n\t}\r\n").ToArray());
                var tsSchemaAndRoutineDefs = string.Join("\r\n", tsSchemaLookup.Select(s => "\t\tclass " + s.Key + " {\r\n" + string.Join(";\r\n", s.Value.ToArray()) + "\r\n\t\t}\r\n").ToArray());

                var finalSB = new StringBuilder(routineContainerTemplate);

                jsFile.IncrementVersion();

                // record changes against new version

                if (changesInFile != null && changesInFile.Count > 0)
                {
                    JsFileChangesTracker.Instance.AddUpdate(endpoint, jsFile, changesInFile.Select(kv => kv.Value).ToList());
                }

                if (rulesChanged)
                {
                    JsFileChangesTracker.Instance.AddUpdate(endpoint, jsFile, new List <ChangeDescriptor> {
                        ChangeDescriptor.Create("System", "One or more rules changed.")
                    });
                }

                finalSB.Replace("<<DATE>>", DateTime.Now.ToString("dd MMM yyyy, HH:mm"))
                .Replace("<<FILE_VERSION>>", jsFile.Version.ToString())
                .Replace("<<SERVER_NAME>>", Environment.MachineName)
                .Replace("<<ENDPOINT>>", endpoint.Pedigree)
                .Replace("<<UNIQUE_SCHEMAS>>", string.Join(',', uniqueSchemas.Select(k => $"'{k}'")))
                .Replace("<<Catalog>>", jsSafeNamespace)
                .Replace("<<ROUTINES>>", schemaAndRoutineDefs)
                ;

                var finalTypeScriptSB = new StringBuilder();

                finalTypeScriptSB = finalTypeScriptSB.Append(typescriptDefinitionsContainer);

                // Custom/User types
                if (endpoint.CustomTypeLookupWithTypeScriptDef.Count > 0)
                {
                    var customTSD = from kv in endpoint.CustomTypeLookupWithTypeScriptDef select $"\t\ttype {kv.Key} = {kv.Value};";
                    typeScriptParameterAndResultTypesSB.Insert(0, string.Join("\r\n", customTSD));
                }

                var resultAndParameterTypes = typeScriptParameterAndResultTypesSB.ToString();

                finalTypeScriptSB.Replace("<<DATE>>", DateTime.Now.ToString("dd MMM yyyy, HH:mm"))
                .Replace("<<FILE_VERSION>>", jsFile.Version.ToString())
                .Replace("<<SERVER_NAME>>", Environment.MachineName)
                .Replace("<<Catalog>>", jsSafeNamespace)
                .Replace("<<ResultAndParameterTypes>>", resultAndParameterTypes)
                .Replace("<<MethodsStubs>>", tsSchemaAndRoutineDefs)
                ;

                finalSBMetric.End();

                var toStringMetric = generateMetric.BeginChildStage("ToString");
                var typescriptDefinitionsOutput = finalTypeScriptSB.ToString();
                var finalOutput = finalSB.ToString();
                toStringMetric.End();

                var filePath          = endpoint.OutputFilePath(jsFile);
                var minfiedFilePath   = endpoint.MinifiedOutputFilePath(jsFile);
                var tsTypingsFilePath = endpoint.OutputTypeScriptTypingsFilePath(jsFile);

                var minifyMetric = generateMetric.BeginChildStage("Minify");

                var minifiedSource = Uglify.Js(finalOutput /*, { }*/).Code;

                minifyMetric.End();

                if (!Directory.Exists(endpoint.OutputDir))
                {
                    Directory.CreateDirectory(endpoint.OutputDir);
                }

                var fileOutputMetric = generateMetric.BeginChildStage("Write");

                var jsFinalBytes         = System.Text.Encoding.UTF8.GetBytes(finalOutput);
                var jsFinalMinifiedBytes = System.Text.Encoding.UTF8.GetBytes(minifiedSource);

                jsFile.ETag         = Controllers.PublicController.ComputeETag(jsFinalBytes);
                jsFile.ETagMinified = Controllers.PublicController.ComputeETag(jsFinalMinifiedBytes);

                File.WriteAllText(filePath, finalOutput);
                File.WriteAllText(minfiedFilePath, minifiedSource);
                File.WriteAllText(tsTypingsFilePath, typescriptDefinitionsOutput);

                fileOutputMetric.End();
            }
            finally
            {
                generateMetric.End();

                SessionLog.InfoToFileOnly($"{endpoint.Pedigree.PadRight(25, ' ')} - {generateMetric.DurationInMS.ToString().PadLeft(4)} ms {jsFile.Filename.PadRight(20)} (source={source};rulesChanged={rulesChanged};changes={!noChanges}); {generateMetric.ChildDurationsSingleLine()}");
            }
        }
コード例 #16
0
        // generates and caches the ServerMethod .js and .tsd for a specific ServerMethod Plugin Registration
        private void GenerateAndCacheJsInterface()
        {
            try
            {
                var definitionsJS  = JavaScriptDefinitions = new Dictionary <string, List <Definition> >();
                var definitionsTSD = TypescriptDefinitions = new Dictionary <string, List <Definition> >();

                JavaScriptDefinitionsHash = TypescriptDefinitionsHash = null;

                ConverterLookup = new List <string>();

                var namespaceLookup = new List <string>();

                // add default namespace
                definitionsJS.Add("ServerMethods", new List <Definition>());
                definitionsTSD.Add("ServerMethods", new List <Definition>());

                foreach (var method in this.Registration.Methods)
                {
                    var namespaceKey    = "ServerMethods";
                    var namespaceKeyTSD = "ServerMethods";
                    var jsNamespaceVar  = Strings.@null; // null for main ServerMethod namespace

                    if (!string.IsNullOrEmpty(method.Namespace))
                    {
                        namespaceKey    = method.Namespace;
                        namespaceKeyTSD = method.Namespace;
                    }

                    var isCustomNamespace = !namespaceKey.Equals("ServerMethods", StringComparison.Ordinal);

                    if (isCustomNamespace)
                    {
                        if (!namespaceLookup.Contains(namespaceKey))
                        {
                            namespaceLookup.Add(namespaceKey);
                        }
                        jsNamespaceVar = $"_ns[{namespaceLookup.IndexOf(namespaceKey)}]";
                    }

                    if (!definitionsJS.ContainsKey(namespaceKey))
                    {
                        definitionsJS.Add(namespaceKey, new List <Definition>());
                    }

                    if (!definitionsTSD.ContainsKey(namespaceKeyTSD))
                    {
                        definitionsTSD.Add(namespaceKeyTSD, new List <Definition>());
                    }

                    var methodParameters = method.AssemblyMethodInfo.GetParameters();

                    var inputConvertersLookup   = new Dictionary <string, ConverterDefinition>();
                    var outputConvertersLookup  = new Dictionary <string, ConverterDefinition>();
                    var resultsConvertersLookup = new Dictionary <string, ConverterDefinition>();

                    foreach (var inputParam in methodParameters)
                    {
                        GlobalConverterLookup.AnalyseForRequiredOutputConverters(inputParam.Name, inputParam.ParameterType, null, ref inputConvertersLookup);
                    }

                    foreach (var outputParam in methodParameters.Where(p => p.IsOut || p.ParameterType.IsByRef))
                    {
                        GlobalConverterLookup.AnalyseForRequiredOutputConverters(outputParam.Name, outputParam.ParameterType, null, ref outputConvertersLookup);
                    }

                    GlobalConverterLookup.AnalyseForRequiredOutputConverters("$result$", method.AssemblyMethodInfo.ReturnType, null, ref resultsConvertersLookup);

                    string inputConverter  = null;
                    string outputConverter = null;
                    string resultConverter = null;

                    var allRequiredConverters = inputConvertersLookup.Select(c => c.Value.ToJson()).Distinct()
                                                .Concat(outputConvertersLookup.Select(c => c.Value.ToJson()).Distinct())
                                                .Concat(resultsConvertersLookup.Select(c => c.Value.ToJson()).Distinct())
                                                .ToList();

                    if (allRequiredConverters.Count > 0)
                    {
                        foreach (var converterJson in allRequiredConverters)
                        {
                            if (ConverterLookup.IndexOf(converterJson) == -1)
                            {
                                ConverterLookup.Add(converterJson);
                            }
                        }
                    }

                    inputConverter = string.Join(",", (from kv in inputConvertersLookup
                                                       select $"\"{kv.Key}\": $c[{kv.Value.ToJson()}]")); // ignore ConverterOptions for now as we don't actually have any use for it at the moment

                    outputConverter = string.Join(",", (from kv in outputConvertersLookup
                                                        select $"\"{kv.Key}\": $c[{kv.Value.ToJson()}]")); // ignore ConverterOptions for now as we don't actually have any use for it at the moment


                    resultConverter = string.Join(",", (from kv in resultsConvertersLookup
                                                        select $"\"{kv.Key}\": $c[{kv.Value.ToJson()}]")); // ignore ConverterOptions for now as we don't actually have any use for it at the moment

                    inputConverter  = string.IsNullOrWhiteSpace(inputConverter) ? null : inputConverter;
                    outputConverter = string.IsNullOrWhiteSpace(outputConverter) ? null : outputConverter;
                    resultConverter = string.IsNullOrWhiteSpace(resultConverter) ? null : resultConverter;

                    var hasConverters = inputConverter != null || outputConverter != null || resultConverter != null;

                    // js
                    var methodLineJS = ServerMethodManager.TEMPLATE_ServerMethodFunctionTemplate
                                       .Replace("<<FUNC_NAME>>", method.Name)
                                       .Replace("<<NAMESPACE>>", jsNamespaceVar);
                    ;

                    if (!hasConverters)
                    {
                        methodLineJS = methodLineJS.Replace("<<CONV_SEP>>", "");
                        methodLineJS = methodLineJS.Replace("<<CONVERTERS>>", "");
                    }

                    if (methodParameters.Count() > 0)
                    {
                        methodLineJS = methodLineJS.Replace("<<ARG_SEP>>", ", ");
                        methodLineJS = methodLineJS.Replace("<<HAS_PARMS>>", "o");
                    }
                    else
                    {
                        methodLineJS = methodLineJS.Replace("<<ARG_SEP>>", "");
                        methodLineJS = methodLineJS.Replace("<<HAS_PARMS>>", "");
                    }

                    definitionsJS[namespaceKey].Add(new Definition()
                    {
                        MethodName = method.Name, Line = methodLineJS, InputConverter = inputConverter, OutputConverter = outputConverter, ResultsConverter = resultConverter
                    });

                    // TSD
                    string methodLineTSD = null;

                    if (isCustomNamespace)
                    {
                        methodLineTSD = SERVER_TSD_METHOD_NONSTATIC_TEMPLATE.Replace("<<FUNC_NAME>>", method.Name);
                    }
                    else
                    {
                        methodLineTSD = SERVER_TSD_METHOD_TEMPLATE.Replace("<<FUNC_NAME>>", method.Name);
                    }

                    var inputParmListLookup = from p in methodParameters
                                              select new
                    {
                        Name = p.Name,
                        p.IsOut,
                        p.ParameterType.IsByRef,
                        p.ParameterType.IsArray,
                        p.ParameterType.IsValueType,
                        HasDefault         = p.IsOptional,
                        IsNullable         = Nullable.GetUnderlyingType(p.ParameterType) != null,
                        TypescriptDataType = GlobalTypescriptTypeLookup.GetTypescriptTypeFromCSharp(p.ParameterType)
                    };

                    var inputParmsFormatted = from p in inputParmListLookup
                                              select $"{p.Name}{((p.HasDefault) ? "?" : "")}: {p.TypescriptDataType}";
                    // TODO: Revise. Not clear if IsNullable should also be output with a '?'. In TypeScript this means optional and not 'nullable'. So in C# even if a parameter is nullable it is still required to specified it. ? should be reserved for OPTIONAL parameters
                    //select $"{p.Name}{((p.HasDefault || p.IsNullable ) ? "?" : "")}: {p.TypescriptDataType}";


                    string typeNameBase        = $"{(isCustomNamespace ? namespaceKeyTSD + "_" : "")}{ method.Name }";
                    string typeNameInputParms  = $"{typeNameBase}_In";
                    string typeNameOutputParms = $"{typeNameBase}_Out";
                    string typeNameResult      = $"{typeNameBase}_Res";

                    string typeDefInputParms  = null;
                    string typeDefOutputParms = null;
                    string typeDefResult      = null;


                    // if there are INPUT parameters
                    if (inputParmsFormatted.Count() > 0)
                    {
                        methodLineTSD = methodLineTSD.Replace("<<PARM_LIST>>", "parameters?: __." + typeNameInputParms);

                        typeDefInputParms  = $"type {typeNameInputParms} = {"{" + string.Join(", ", inputParmsFormatted) + "}"};";
                        typeNameInputParms = "__." + typeNameInputParms;
                    }
                    else
                    {
                        methodLineTSD      = methodLineTSD.Replace("<<PARM_LIST>>", "");
                        typeNameInputParms = "void";
                    }

                    // if there are OUTPUT parameters
                    if (inputParmListLookup.Count(p => p.IsOut) > 0)
                    {
                        typeDefOutputParms = $"type {typeNameOutputParms} = {{ " + string.Join(", ", (from p in inputParmListLookup
                                                                                                      where p.IsOut
                                                                                                      select $"{p.Name}: {p.TypescriptDataType}")) + " };";
                        typeNameOutputParms = "__." + typeNameOutputParms;
                    }
                    else
                    {
                        typeNameOutputParms = "void";
                    }


                    if (method.AssemblyMethodInfo.ReturnType == typeof(void)) // no result
                    {
                        //IServerMethodVoid<OuputParameters, InputParameters>
                        methodLineTSD = methodLineTSD.Replace("<<RET_TYPE>>", $"IServerMethodVoid<{typeNameOutputParms}, {typeNameInputParms}>");
                    }
                    else
                    {
                        //IServerMethod<OuputParameters, ResultType, InputParameters>

                        var retType = GlobalTypescriptTypeLookup.GetTypescriptTypeFromCSharp(method.AssemblyMethodInfo.ReturnType);

                        // if a built-in js/TS type
                        if (new string[] { "number", "string", "date", "boolean", "any", "number[]", "string[]", "date[]", "boolean[]", "any[]" }.Contains(retType.ToLower()))
                        {
                            typeDefResult = null;
                            methodLineTSD = methodLineTSD.Replace("<<RET_TYPE>>", $"IServerMethod<{typeNameOutputParms}, {retType}, {typeNameInputParms}>");
                        }
                        else
                        {
                            typeDefResult = $"type {typeNameResult} = {retType};";
                            methodLineTSD = methodLineTSD.Replace("<<RET_TYPE>>", $"IServerMethod<{typeNameOutputParms}, __.{typeNameResult}, {typeNameInputParms}>");
                        }
                    }

                    definitionsTSD[namespaceKeyTSD].Add(new Definition()
                    {
                        MethodName = method.Name, Line = methodLineTSD, TypesLines = new List <string>()
                        {
                            typeDefInputParms, typeDefOutputParms, typeDefResult
                        }
                    });
                } // foreach (var method in this.Methods)


                var jsLines  = string.Join("\n", definitionsJS.Select(kv => $"{kv.Key}§{string.Join('\n', kv.Value.Select(d => d.Line).ToArray())}").ToArray());
                var tsdLines = string.Join("\n", definitionsTSD.Select(kv => $"{kv.Key}§{string.Join('\n', kv.Value.Select(d => d.Line).ToArray())}").ToArray());

                using (var sha = System.Security.Cryptography.SHA256.Create())
                {
                    var jsHash  = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(jsLines));
                    var tsdHash = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(tsdLines));

                    // TODO: Compare with current Hashes. If different then let all relevant Apps know

                    this.JavaScriptDefinitionsHash = jsHash;
                    this.TypescriptDefinitionsHash = tsdHash;
                }
            }
            catch (Exception ex)
            {
                SessionLog.Exception(ex);
            }
        }
コード例 #17
0
        // public static async Task<(bool, List<string>)> Evaluate(string code)
        // {
        //     try
        //     {
        //         var options = ScriptOptions.Default.WithReferences(GetCommonMetadataReferences());

        //         await CSharpScript.EvaluateAsync(code, options, globals: null, globalsType: null, cancellationToken: CancellationToken.None);

        //         return (true, null);
        //     }
        //     catch (CompilationErrorException ce)
        //     {
        //         return (false, (from d in ce.Diagnostics
        //                         select d.ToString()).ToList());
        //     }
        // }

        // public static async Task<(bool/*isValid*/, List<string>/*problems*/, List<BasePluginRuntime>/*parsedPluginCollection*/)> EvalAndParseAsync(string id, string code)
        // {
        //     bool isValid;
        //     List<string> problems = null;
        //     List<BasePluginRuntime> parsedPluginCollection = null;

        //     (isValid, problems) = await CSharpCompilerHelper.Evaluate(code);

        //     if (isValid) // if compilation went well
        //     {
        //         isValid = CSharpCompilerHelper.ParseForPluginTypes(id, code, out parsedPluginCollection, out problems);
        //     }

        //     return (isValid, problems, parsedPluginCollection);
        // }

        public static byte[] CompileIntoAssembly(string assemblyName, string source, out List <string> problems)
        {
            problems = new List <string>();

            try
            {
                if (string.IsNullOrEmpty(assemblyName))
                {
                    problems.Add("Assembly name must have a value");
                }

                if (string.IsNullOrEmpty(source))
                {
                    problems.Add("No source provided");
                }

                if (problems.Count > 0)
                {
                    return(null);
                }

                CSharpParseOptions parseOptions = CSharpParseOptions.Default;

                SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source, options: parseOptions);

                // if (Debugger.IsAttached)
                // {
                //     pluginBasePath = "./../jsdal-plugin/bin/Debug/netcoreapp2.0/jsdal-plugin.dll";
                // }

                //var pluginBaseRef = MetadataReference.CreateFromFile(pluginBasePath);

                //var trustedAssembliesPaths = ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")).Split(Path.PathSeparator);

                MetadataReference[] references = GetCommonMetadataReferences();


                var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                                         .WithUsings(new string[] { "System" });

                CSharpCompilation compilation = CSharpCompilation.Create(
                    assemblyName,
                    syntaxTrees: new[] { syntaxTree },
                    references: references,
                    options: compilationOptions
                    );


                using (var ms = new MemoryStream())
                {
                    EmitResult result = compilation.Emit(ms);

                    if (!result.Success)
                    {
                        IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
                                                                                     diagnostic.IsWarningAsError ||
                                                                                     diagnostic.Severity == DiagnosticSeverity.Error);

                        problems = failures.Select(f => f.GetMessage()).ToList();

                        foreach (Diagnostic diagnostic in failures)
                        {
                            Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
                        }

                        return(null);
                    }
                    else
                    {
                        ms.Seek(0, SeekOrigin.Begin);

                        //?AssemblyLoadContext.Default.LoadFromStream



                        //Assembly assembly = Assembly.Load(ms.ToArray());

                        //?var assembly = asmCtx.LoadFromStream(ms);
                        return(ms.ToArray());
                        //ParseAndLoadPluginAssembly(assembly);
                    }
                }
            }
            catch (Exception ex)
            {
                problems.Add(ex.ToString());
                SessionLog.Exception(ex);
                return(null);
            }
        }
コード例 #18
0
        //AssemblyLoadContext, AssemblyName, Assembly?
        // private Assembly OnResolveAssembly(AssemblyLoadContext ctx, AssemblyName asmName)
        // {
        //     try
        //     {
        //         // try and find relative to existing assebmlies loaded in ctx
        //         foreach (var asm in ctx.Assemblies)
        //         {
        //             var fi = new FileInfo(asm.Location);

        //             var path = Path.Combine(fi.DirectoryName, asmName.Name + ".dll");

        //             if (File.Exists(path))
        //             {
        //                 try
        //                 {
        //                     var loadedAsm = ctx.LoadFromAssemblyPath(path);
        //                     if (loadedAsm != null) return loadedAsm;
        //                 }
        //                 catch { }
        //             }
        //         }

        //         SessionLog.Error($"Failed to resolve {asmName.FullName} in context {ctx.Name}");
        //         return null;
        //     }
        //     catch
        //     {
        //         return null;
        //     }
        // }

        // private Assembly OnResolveAssembly(object sender, ResolveEventArgs e)
        // {
        //     try
        //     {
        //         var asmName = new AssemblyName(e.Name);
        //         var requestingLocation = e.RequestingAssembly.Location;
        //         var requestingDir = Path.GetDirectoryName(requestingLocation);

        //         // look for a dll in the same location as the requesting assembly
        //         var path = Path.Combine(requestingDir, asmName.Name + ".dll");

        //         if (!File.Exists(path)) return null;

        //         Assembly.LoadFrom(path);

        //         return null;
        //     }
        //     catch
        //     {
        //         return null;
        //     }
        // }

        // private void InitServerWidePlugins()
        // {
        //     try
        //     {
        //         if (PluginAssemblies == null) return;

        //         foreach (var pluginAssembly in PluginAssemblies)
        //         {
        //             var pluginInfoCollection = pluginAssembly.Plugins.Where(p => p.Type == OM.PluginType.ServerMethod || p.Type == OM.PluginType.BackgroundThread);

        //             foreach (var pluginInfo in pluginInfoCollection)
        //             {
        //                 if (pluginInfo.Type == OM.PluginType.BackgroundThread)
        //                 {
        //                     _backgroundThreadManager.Register(pluginInfo);
        //                 }
        //                 else if (pluginInfo.Type == OM.PluginType.ServerMethod)
        //                 {
        //                     ServerMethodManager.Register(pluginAssembly.InstanceId, pluginInfo);
        //                 }
        //             }
        //         }
        //     }
        //     catch (Exception ex)
        //     {
        //         SessionLog.Exception(ex);
        //     }
        // }


        // parses an Assembly and checks for Plugin-type interface. If found each of those interfaces are tested for validity in terms of mandatory Attribute values and uniqueness
        private bool ParsePluginAssembly(Assembly pluginAssembly, out List <PluginInfo> pluginInfoList, out List <string> errorList, bool checkForConflict = true)
        {
            errorList      = new List <string>();
            pluginInfoList = new List <PluginInfo>();

            if (pluginAssembly.DefinedTypes != null)
            {
                var pluginTypeList = pluginAssembly.DefinedTypes.Where(typ => typ.IsSubclassOf(typeof(PluginBase))).ToList();

                if (pluginTypeList != null && pluginTypeList.Count > 0)
                {
                    foreach (var pluginType in pluginTypeList)
                    {
                        var pluginInfo = new PluginInfo();

                        try
                        {
                            var pluginData = pluginType.GetCustomAttribute(typeof(PluginDataAttribute)) as PluginDataAttribute;

                            if (pluginData == null)
                            {
                                errorList.Add($"Plugin '{pluginType.FullName}' from assembly '{pluginAssembly.FullName}' does not have a PluginData attribute defined on the class level. Add a jsdal_plugin.PluginDataAttribute to the class.");
                                continue;
                            }

                            if (!Guid.TryParse(pluginData.Guid, out var pluginGuid))
                            {
                                errorList.Add($"Plugin '{pluginType.FullName}' does not have a valid Guid value set on its PluginData attribute.");
                                continue;
                            }

                            if (checkForConflict)
                            {
                                var conflict = PluginAssemblies.SelectMany(a => a.Plugins).FirstOrDefault(p => p.Guid.Equals(pluginGuid));

                                if (conflict != null)
                                {
                                    errorList.Add($"Plugin '{pluginType.FullName}' has a conflicting Guid. The conflict is on assembly {conflict.TypeInfo.FullName} and plugin '{conflict.Name}' with Guid value {conflict.Guid}.");
                                    continue;
                                }
                            }

                            if (pluginType.IsSubclassOf(typeof(ExecutionPlugin)))
                            {
                                pluginInfo.Type = OM.PluginType.Execution;
                            }
                            else if (pluginType.IsSubclassOf(typeof(BackgroundThreadPlugin)))
                            {
                                pluginInfo.Type = OM.PluginType.BackgroundThread;
                            }
                            else if (pluginType.IsSubclassOf(typeof(ServerMethodPlugin)))
                            {
                                pluginInfo.Type = OM.PluginType.ServerMethod;


                                // TODO: Additional validation: Look for at least on ServerMethod? otherwise just a warning?
                                //      What about unique names of ServerMethods?
                                //      Validate Custom Namespace validity (must be JavaScript safe)
                            }
                            else
                            {
                                errorList.Add($"Unknown plugin type '{pluginType.FullName}'.");
                                continue;
                            }

                            pluginInfo.Assembly    = pluginAssembly;
                            pluginInfo.Name        = pluginData.Name;
                            pluginInfo.Description = pluginData.Description;
                            pluginInfo.TypeInfo    = pluginType;
                            pluginInfo.Guid        = pluginGuid;

                            //errorList.Add($"Plugin '{pluginInfo.Name}' ({pluginInfo.Guid}) loaded. Assembly: {pluginAssembly.FullName}");
                            pluginInfoList.Add(pluginInfo);
                        }
                        catch (Exception ex)
                        {
                            errorList.Add("Failed to instantiate type '{pluginType.FullName}'.");
                            errorList.Add(ex.ToString());

                            SessionLog.Error("Failed to instantiate type '{0}'. See the exception that follows.", pluginType.FullName);
                            SessionLog.Exception(ex);
                        }
                    }
                }
                else
                {
                    errorList.Add($"Failed to find any jsDAL Server plugins in the assembly '{pluginAssembly.Location}'. Make sure you have a public class available that derives from one of the plugin types.");
                }
            }
            else
            {
                errorList.Add($"Failed to find any jsDAL Server plugins in the assembly '{pluginAssembly.Location}'. Make sure you have a public class available that derives from one of the plugin types.");
            }

            return(errorList == null || errorList.Count == 0);
        }
コード例 #19
0
        public static void Main(string[] args)
        {
            IsShuttingDown = false;

            var loggerConfig = new LoggerConfiguration()
                               .MinimumLevel.Debug()
                               .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                               .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
                               .Enrich.FromLogContext()

                               .WriteTo.File("log/detail-.txt",
                                             //?restrictedToMinimumLevel: LogEventLevel.Warning,
                                             rollingInterval: RollingInterval.Day,
                                             retainedFileCountLimit: 7,
                                             shared: true,
                                             outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3} {Message:lj}{NewLine}{Exception}"
                                             )
                               // .WriteTo.File("log/info-.txt",
                               //         rollingInterval: RollingInterval.Day,
                               //         shared: true,
                               //         outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3} {Message:lj}{NewLine}{Exception}",
                               //         restrictedToMinimumLevel: LogEventLevel.Information
                               //         )
            ;

            try
            {
                CTS = new CancellationTokenSource();

                var isService = args.Length == 1 && args[0].Equals("--service", StringComparison.OrdinalIgnoreCase);
                var justRun   = args.Length == 1 && args[0].Equals("--run", StringComparison.OrdinalIgnoreCase);

                if (isService)
                {
                    var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
                    var pathToContentRootService = Path.GetDirectoryName(pathToExe);
                    Directory.SetCurrentDirectory(pathToContentRootService);
                }
                else if (!Debugger.IsAttached && !justRun)
                {
                    TerminalUI.Init();
                    return;
                }
                else
                {
                    loggerConfig.WriteTo.Console();
                }

                Log.Logger = loggerConfig.CreateLogger();

                var pathToContentRoot = Directory.GetCurrentDirectory();

                if (Debugger.IsAttached)
                {
                    // var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
                    //  pathToContentRoot = Path.GetDirectoryName(pathToExe);
                }
                else
                {
                    // now relying on serilog
                    // OverrideStdout();
                }

                AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
                {
                    var isTerminating = e.IsTerminating;

                    Log.Fatal("Unhandled exception", e.ExceptionObject);
                    ExceptionLogger.LogException(e.ExceptionObject as Exception);
                };

                AppConfigSettings appConfigSettings = null;

                try
                {
                    var appSettingsJson = File.ReadAllText("./appsettings.json");

                    appConfigSettings = System.Text.Json.JsonSerializer.Deserialize <AppConfigSettings>(appSettingsJson);
                }
                catch (Exception ex)
                {
                    Log.Error(ex, "Failed to read appsettings.json");
                }

                _startDate = DateTime.Now;

                var _ = UptimeLogger.LogServerUptimeAsync();

                Log.Information($"Application started with process id {System.Diagnostics.Process.GetCurrentProcess().Id}.");

                // I forget what the different msg types look like
                Log.Warning("This is what a warning looks like");
                Log.Error("This is what an error looks like");
                Log.Fatal("This is what a fatal error looks like");

                Log.Information("Loading users");
                UserManagement.LoadUsersFromFile();

                Log.Information("Initialising exception logger");
                ExceptionLogger.Instance.Init();

                Log.Information("Loading settings");
                SettingsInstance.LoadSettingsFromFile();

                Log.Information("Initialising real-time tracker");
                RealtimeTrackerThread.Instance.Init();

                if (appConfigSettings?.AppSettings?.Startup?.HealthMonitor ?? false)
                {
                    Log.Information("Initialising jsDAL health monitor");
                    jsDALHealthMonitorThread.Instance.Init();
                }
                else
                {
                    Log.Information("jsDAL health monitor not configured to run at startup");
                }

                if (appConfigSettings?.AppSettings?.Startup?.DataCollector ?? false)
                {
                    Log.Information("Initialising data collector");
                    DataCollectorThread.Instance.Init();
                }
                else
                {
                    Log.Information("Data collector not configured to run at startup");
                }

                Log.Information("Initialising inline module manifest");
                InlineModuleManifest.Instance.Init();


                Log.Information("Configuring global culture");
                var globalCulture = new System.Globalization.CultureInfo("en-US");

                // set global culture to en-US - will help with things like parsing numbers from Javascript(e.g. 10.123) as double/decimal even if server uses a comma as decimal separator for example
                CultureInfo.DefaultThreadCurrentCulture   = globalCulture;
                CultureInfo.DefaultThreadCurrentUICulture = globalCulture;

                Log.Information("Building web host");
                var builder = BuildWebHost(pathToContentRoot, args);
                var host    = builder.Build();

                if (isService)
                {
                    host.RunAsCustomService();
                }
                else
                {
                    host.RunAsync();

                    Console.WriteLine("\r\nPress CTRL+X to shutdown server");

                    while (true)
                    {
                        var keyInfo = Console.ReadKey(true);

                        if (keyInfo.Key == ConsoleKey.X && (keyInfo.Modifiers & ConsoleModifiers.Control) == ConsoleModifiers.Control)
                        {
                            //host.StopAsync();
                            ShutdownAllBackgroundThreads();
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "Application terminated unexpectedly");
                SessionLog.Exception(ex);

                ShutdownAllBackgroundThreads();
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }
コード例 #20
0
        public async Task InitAsync()
        {
            // load from plugin directory
            try
            {
                // AppDomain.CurrentDomain.AssemblyResolve += (sender, e) =>
                // {
                //     try
                //     {
                //         var asmName = new AssemblyName(e.Name);
                //         var requestingLocation = e.RequestingAssembly.Location;
                //         var requestingDir = Path.GetDirectoryName(requestingLocation);

                //         // look for a dll in the same location as the requesting assembly
                //         var path = Path.Combine(requestingDir, asmName.Name + ".dll");

                //         if (!File.Exists(path)) return null;

                //         Assembly.LoadFrom(path);

                //         return null;
                //     }
                //     catch
                //     {
                //         return null;
                //     }
                // };

                var pluginPath = Path.GetFullPath("plugins");

                if (Directory.Exists("./plugins"))
                {
                    var dllCollection = Directory.EnumerateFiles("plugins", "*.dll", SearchOption.TopDirectoryOnly);

                    foreach (var dllPath in dllCollection)
                    {
                        // skip jsdal-plugin base
                        if (dllPath.Equals("plugins\\jsdal-plugin.dll", StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }

                        try
                        {
                            var ctxName = $"Plugin Context {++_asmCtxCounter}";
                            var asmCtx  = new PluginAssemblyLoadContext(pluginPath, ctxName, true /*enable unloading*/);
                            ASM_CTXES.Add(asmCtx);
                            SessionLog.Info($"Created {ctxName} for {dllPath}".PadRight(35));


                            var dllFullPath    = Path.GetFullPath(dllPath);
                            var pluginAssembly = asmCtx.LoadFromAssemblyPath(dllFullPath);

                            ParseAndLoadPluginAssembly(asmCtx, pluginAssembly, null);
                        }
                        catch (Exception ee)
                        {
                            SessionLog.Error("Failed to load plugin DLL '{0}'. See exception that follows.", dllPath);
                            SessionLog.Exception(ee);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                SessionLog.Exception(ex);
            }

            // load inline assemblies
            try
            {
                foreach (var inlineEntry in InlineModuleManifest.Instance.Entries)
                {
                    var sourcePath = Path.Combine(InlinePluginSourcePath, inlineEntry.Id);

                    if (File.Exists(sourcePath))
                    {
                        var code = await File.ReadAllTextAsync(sourcePath);

                        CompileCodeIntoAssemblyContext(inlineEntry, code);
                    }
                    else
                    {
                        SessionLog.Error($"Inline module {inlineEntry.Name} not found at '{sourcePath}'");
                    }
                }
            }
            catch (Exception ex)
            {
                SessionLog.Exception(ex);
            }

            // init server-wide types
            // try
            // {
            //     InitServerWidePlugins();
            // }
            // catch (Exception ex)
            // {
            //     SessionLog.Exception(ex);
            // }
        }