6424e14bf5cc49dbcbb08faa6d9c171641d2b4bd
[platform/core/dotnet/launcher.git] / Managed / Tizen.Runtime / Preloader.cs
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.IO;
19 using System.Reflection;
20 using System.Runtime.Loader;
21 using System.Globalization;
22 using System.Runtime.CompilerServices;
23
24 namespace Tizen.Runtime
25 {
26     public class Preloader
27     {
28         const string preloadPath = "/usr/share/dotnet.tizen/preload/";
29
30         // If current culture's casing for ASCII is the same as invariant, it can take a fast path
31         // than calling out to the OS for culture-aware casing.
32         // However, in certain languages, the following function may be significantly slowed down.
33         // To avoid that kind situation, call it in advance on the candidate process.
34         [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
35         private static void CheckAsciiCasing()
36         {
37             _ = CultureInfo.CurrentCulture.CompareInfo.Compare("abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", CompareOptions.IgnoreCase);
38             _ = "abc".ToUpper().ToLower();
39         }
40
41         public static void Preload()
42         {
43             CheckAsciiCasing();
44
45             if (!Directory.Exists(preloadPath))
46                 return;
47
48             string[] paths = Directory.GetFiles(preloadPath, "*.preload");
49             Array.Sort(paths);
50             foreach (string path in paths)
51             {
52                 string fileName = Path.GetFileName(path);
53
54                 // GetFileName() can return NULL
55                 if (fileName == null)
56                     continue;
57
58                 // ex) Tizen.preload / 0A.Tizen.preload / A0.Tizen.preload / .0.Tizen.preload / .00.Tizen.preload
59                 if (!char.IsNumber(fileName, 0) || !char.IsNumber(fileName, 1))
60                     continue;
61
62                 // ex) 000.Tizen.preload / 0.Tizen.preload
63                 if (fileName.IndexOf('.') != 2)
64                     continue;
65
66                 string value = System.Environment.GetEnvironmentVariable("TIZEN_UIFW");
67                 // if TIZEN_UIFW is not set, do not preload UI related dll
68                 if (value == null && (fileName.Contains("NUI") || fileName.Contains("ElmSharp") || fileName.Contains("XSF") ))
69                     continue;
70                 else if (value == "ElmSharp" && fileName.Contains("NUI"))
71                     continue;
72                 else if (value == "NUI" && (fileName.Contains("ElmSharp") || fileName.Contains("XSF")))
73                     continue;
74
75                 try
76                 {
77                     Console.WriteLine("Start preload : " + fileName);
78                     BindingFlags bindingFlag = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
79                     foreach (string line in File.ReadLines(path))
80                     {
81                         if (line.StartsWith('#') || !line.Contains(".dll") || !line.Contains(' '))
82                             continue;
83
84                         string[] getWord = line.Split(' ');
85                         if (getWord.Length != 2)
86                             continue;
87
88                         string assemblyStr = getWord[0].Replace(".dll", "");
89                         string typenameStr = getWord[1];
90                         string methodStr = "";
91                         string parenthesis = "()";
92
93                         if (line.Contains(parenthesis))
94                         {
95                             string[] getMethod = typenameStr.Split('.');
96                             methodStr = getMethod[getMethod.Length - 1].Replace(parenthesis, "");
97                             typenameStr = typenameStr.Replace("." + methodStr + parenthesis, "");
98                         }
99
100                         if (assemblyStr == "")
101                         {
102                             Console.WriteLine("[Warning] Skip the '" + line + "' in " + fileName);
103                             continue;
104                         }
105
106                         try
107                         {
108                             Assembly asm = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyStr));
109                             if (asm == null)
110                             {
111                                 Console.WriteLine("[Warning] Check the '" + line + "' in " + fileName);
112                                 continue;
113                             }
114
115                             if (typenameStr != "" && !typenameStr.Contains(parenthesis))
116                             {
117                                 Type type = asm.GetType(typenameStr);
118                                 if (type == null)
119                                 {
120                                     Console.WriteLine("[Warning] Check the '" + line + "' in " + fileName);
121                                     continue;
122                                 }
123
124                                 if (methodStr != "")
125                                 {
126                                     MethodInfo method = type.GetMethod(methodStr, bindingFlag);
127                                     if (method == null)
128                                     {
129                                         Console.WriteLine("[Warning] Check the '" + line + "' in " + fileName);
130                                         continue;
131                                     }
132                                     method.Invoke(null, null);
133                                 }
134                             }
135                         }
136                         catch
137                         {
138                             Console.WriteLine("[Error] Fail the '" + line + "' in " + fileName);
139                         }
140                     }
141                 }
142                 catch (IOException e)
143                 {
144                     Console.WriteLine(e.ToString());
145                     Console.WriteLine("[Error] Failed to open file : " + fileName);
146                 }
147             }
148
149             GC.Collect();
150             GC.WaitForPendingFinalizers();
151
152             Profiler.SetCandidateProcessProfile();
153         }
154     }
155 }