afb614d4d21a8bd14fef4754d0ac5258f1fac701
[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
23 namespace Tizen.Runtime
24 {
25     public class Preloader
26     {
27         const string preloadPath = "/usr/share/dotnet.tizen/preload/";
28
29         // If current culture's casing for ASCII is the same as invariant, it can take a fast path
30         // than calling out to the OS for culture-aware casing.
31         // However, in certain languages, the following function may be significantly slowed down.
32         // To avoid that kind situation, call it in advance on the candidate process.
33         private static void CheckAsciiCasing()
34         {
35             _ = CultureInfo.CurrentCulture.CompareInfo.Compare("abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", CompareOptions.IgnoreCase);
36         }
37
38         public static void Preload()
39         {
40             CheckAsciiCasing();
41
42             if (!Directory.Exists(preloadPath))
43                 return;
44
45             string[] paths = Directory.GetFiles(preloadPath, "*.preload");
46             Array.Sort(paths);
47             foreach (string path in paths)
48             {
49                 string fileName = Path.GetFileName(path);
50
51                 // GetFileName() can return NULL
52                 if (fileName == null)
53                     continue;
54
55                 // ex) Tizen.preload / 0A.Tizen.preload / A0.Tizen.preload / .0.Tizen.preload / .00.Tizen.preload
56                 if (!char.IsNumber(fileName, 0) || !char.IsNumber(fileName, 1))
57                     continue;
58
59                 // ex) 000.Tizen.preload / 0.Tizen.preload
60                 if (fileName.IndexOf('.') != 2)
61                     continue;
62
63                 string value = System.Environment.GetEnvironmentVariable("TIZEN_UIFW");
64                 // if TIZEN_UIFW is not set, do not preload UI related dll
65                 if (value == null && (fileName.Contains("NUI") || fileName.Contains("ElmSharp") || fileName.Contains("XSF") ))
66                     continue;
67                 else if (value == "ElmSharp" && fileName.Contains("NUI"))
68                     continue;
69                 else if (value == "NUI" && (fileName.Contains("ElmSharp") || fileName.Contains("XSF")))
70                     continue;
71
72                 try
73                 {
74                     Console.WriteLine("Start preload : " + fileName);
75                     BindingFlags bindingFlag = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
76                     foreach (string line in File.ReadLines(path))
77                     {
78                         if (line.StartsWith('#') || !line.Contains(".dll") || !line.Contains(' '))
79                             continue;
80
81                         string[] getWord = line.Split(' ');
82                         if (getWord.Length != 2)
83                             continue;
84
85                         string assemblyStr = getWord[0].Replace(".dll", "");
86                         string typenameStr = getWord[1];
87                         string methodStr = "";
88                         string parenthesis = "()";
89
90                         if (line.Contains(parenthesis))
91                         {
92                             string[] getMethod = typenameStr.Split('.');
93                             methodStr = getMethod[getMethod.Length - 1].Replace(parenthesis, "");
94                             typenameStr = typenameStr.Replace("." + methodStr + parenthesis, "");
95                         }
96
97                         if (assemblyStr == "")
98                         {
99                             Console.WriteLine("[Warning] Skip the '" + line + "' in " + fileName);
100                             continue;
101                         }
102
103                         try
104                         {
105                             Assembly asm = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyStr));
106                             if (asm == null)
107                             {
108                                 Console.WriteLine("[Warning] Check the '" + line + "' in " + fileName);
109                                 continue;
110                             }
111
112                             if (typenameStr != "" && !typenameStr.Contains(parenthesis))
113                             {
114                                 Type type = asm.GetType(typenameStr);
115                                 if (type == null)
116                                 {
117                                     Console.WriteLine("[Warning] Check the '" + line + "' in " + fileName);
118                                     continue;
119                                 }
120
121                                 if (methodStr != "")
122                                 {
123                                     MethodInfo method = type.GetMethod(methodStr, bindingFlag);
124                                     if (method == null)
125                                     {
126                                         Console.WriteLine("[Warning] Check the '" + line + "' in " + fileName);
127                                         continue;
128                                     }
129                                     method.Invoke(null, null);
130                                 }
131                             }
132                         }
133                         catch
134                         {
135                             Console.WriteLine("[Error] Fail the '" + line + "' in " + fileName);
136                         }
137                     }
138                 }
139                 catch (IOException e)
140                 {
141                     Console.WriteLine(e.ToString());
142                     Console.WriteLine("[Error] Failed to open file : " + fileName);
143                 }
144             }
145
146             GC.Collect();
147             GC.WaitForPendingFinalizers();
148
149             Profiler.SetCandidateProcessProfile();
150         }
151     }
152 }