ea0737b484849398b4bc8dd3c3fa0f9d8e188803
[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 CoreclrPreload()
42         {
43             CheckAsciiCasing();
44         }
45
46         public static void Preload()
47         {
48             CheckAsciiCasing();
49
50             if (!Directory.Exists(preloadPath))
51                 return;
52
53             // If TIZEN_UIFW is not set or NUI, do not preload UI related dll
54             string uifw = System.Environment.GetEnvironmentVariable("TIZEN_UIFW");
55             if (uifw == null || uifw != "NUI")
56                 return;
57
58             string[] paths = Directory.GetFiles(preloadPath, "*.preload");
59             Array.Sort(paths);
60             foreach (string path in paths)
61             {
62                 string fileName = Path.GetFileName(path);
63
64                 // GetFileName() can return NULL
65                 if (fileName == null)
66                     continue;
67
68                 // ex) Tizen.preload / 0A.Tizen.preload / A0.Tizen.preload / .0.Tizen.preload / .00.Tizen.preload
69                 if (!char.IsNumber(fileName, 0) || !char.IsNumber(fileName, 1))
70                     continue;
71
72                 // ex) 000.Tizen.preload / 0.Tizen.preload
73                 if (fileName.IndexOf('.') != 2)
74                     continue;
75
76                 // TIZEN_UIFW only set NUI
77                 if (fileName.Contains("ElmSharp") || fileName.Contains("XSF"))
78                     continue;
79
80                 try
81                 {
82                     Console.WriteLine("UIFW: " + uifw + " Start preload : " + fileName);
83                     BindingFlags bindingFlag = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
84                     foreach (string line in File.ReadLines(path))
85                     {
86                         if (line.StartsWith('#') || !line.Contains(".dll") || !line.Contains(' '))
87                             continue;
88
89                         string[] getWord = line.Split(' ');
90                         if (getWord.Length != 2)
91                             continue;
92
93                         string assemblyStr = getWord[0].Replace(".dll", "");
94                         string typenameStr = getWord[1];
95                         string methodStr = "";
96                         string parenthesis = "()";
97
98                         if (line.Contains(parenthesis))
99                         {
100                             string[] getMethod = typenameStr.Split('.');
101                             methodStr = getMethod[getMethod.Length - 1].Replace(parenthesis, "");
102                             typenameStr = typenameStr.Replace("." + methodStr + parenthesis, "");
103                         }
104
105                         if (assemblyStr == "")
106                         {
107                             Console.WriteLine("[Warning] Skip the '" + line + "' in " + fileName);
108                             continue;
109                         }
110
111                         try
112                         {
113                             Assembly asm = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyStr));
114                             if (asm == null)
115                             {
116                                 Console.WriteLine("[Warning] Check the '" + line + "' in " + fileName);
117                                 continue;
118                             }
119
120                             if (typenameStr != "" && !typenameStr.Contains(parenthesis))
121                             {
122                                 Type type = asm.GetType(typenameStr);
123                                 if (type == null)
124                                 {
125                                     Console.WriteLine("[Warning] Check the '" + line + "' in " + fileName);
126                                     continue;
127                                 }
128
129                                 if (methodStr != "")
130                                 {
131                                     MethodInfo method = type.GetMethod(methodStr, bindingFlag);
132                                     if (method == null)
133                                     {
134                                         Console.WriteLine("[Warning] Check the '" + line + "' in " + fileName);
135                                         continue;
136                                     }
137                                     method.Invoke(null, null);
138                                 }
139                             }
140                         }
141                         catch
142                         {
143                             Console.WriteLine("[Error] Fail the '" + line + "' in " + fileName);
144                         }
145                     }
146                 }
147                 catch (IOException e)
148                 {
149                     Console.WriteLine(e.ToString());
150                     Console.WriteLine("[Error] Failed to open file : " + fileName);
151                 }
152             }
153
154             GC.Collect();
155             GC.WaitForPendingFinalizers();
156
157             Profiler.SetCandidateProcessProfile();
158         }
159     }
160 }