Basename bug fixed
[platform/core/dotnet/launcher.git] / Tizen.Runtime / CoreClr / AssemblyLoader.cs
1 /*
2  * Copyright (c) 2016 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.Linq;
20 using System.Reflection;
21 using System.Runtime.Loader;
22 using System.Collections.Generic;
23
24 namespace Tizen.Runtime.Coreclr
25 {
26     public class AssemblyLoader : AssemblyLoadContext
27     {
28         private const string NativeAssemblyInfix = ".ni";
29         private const string DllAssemblySuffix = ".dll";
30         private const string ExeAssemblySuffix = ".exe";
31         private const string NativeDllAssemblySuffix = NativeAssemblyInfix + DllAssemblySuffix;
32         private static readonly string[] Suffixes = new string[] { NativeDllAssemblySuffix, DllAssemblySuffix, ExeAssemblySuffix };
33         private SortedSet<string> DllDirectoriesSet = new SortedSet<string>();
34         private SortedSet<string> NativeDirectoriesSet = new SortedSet<string>();
35         private HashSet<FileInfo> AssemblyCacheSet = new HashSet<FileInfo>();
36
37         public AssemblyLoader()
38         {
39             AssemblyLoadContext.Default.Resolving += OnResolving;
40         }
41
42         public IEnumerable<string> DllDirectories
43         {
44             get { return DllDirectoriesSet; }
45         }
46
47         public IEnumerable<string> NativeDirectories
48         {
49             get { return NativeDirectoriesSet; }
50         }
51
52         public void AddSearchableDirectory(string directory)
53         {
54             if (Directory.Exists(directory))
55             {
56                 DllDirectoriesSet.Add(directory);
57                 NativeDirectoriesSet.Add(directory);
58
59                 foreach (var file in Directory.GetFiles(directory))
60                 {
61                     var info = new FileInfo(file);
62
63                     if (Suffixes.Contains(info.Extension))
64                     {
65                         AssemblyCacheSet.Add(info);
66                     }
67                 }
68             }
69         }
70
71         public void RemoveSearchableDirectory(string directory)
72         {
73             DllDirectoriesSet.Remove(directory);
74             NativeDirectoriesSet.Remove(directory);
75
76             AssemblyCacheSet.RemoveWhere(x => x.DirectoryName == directory);
77         }
78
79         public Assembly LoadFromPath(string path)
80         {
81             if (string.Compare(path, path.Length - NativeDllAssemblySuffix.Length, NativeAssemblyInfix, 0, NativeAssemblyInfix.Length, StringComparison.OrdinalIgnoreCase) == 0)
82             {
83                 return LoadFromNativeImagePath(path, null);
84             }
85             else
86             {
87                 return LoadFromAssemblyPath(path);
88             }
89         }
90
91         protected override Assembly Load(AssemblyName assemblyName)
92         {
93             return Resolve(assemblyName);
94         }
95
96         protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
97         {
98             IntPtr native = base.LoadUnmanagedDll(unmanagedDllName);
99             if (native == IntPtr.Zero)
100             {
101                 foreach (string dir in NativeDirectories)
102                 {
103                     FileInfo f = new FileInfo(Path.Combine(dir, unmanagedDllName));
104                     if (File.Exists(f.FullName))
105                     {
106                         native = LoadUnmanagedDllFromPath(f.FullName);
107                         break;
108                     }
109                 }
110             }
111
112             return native;
113         }
114
115         private Assembly Resolve(AssemblyName assemblyName)
116         {
117             foreach (string suffix in Suffixes)
118             {
119                 var info = AssemblyCacheSet.FirstOrDefault(x => x.Name == assemblyName.Name + suffix);
120
121                 if (info != null)
122                 {
123                     return LoadFromPath(info.FullName);
124                 }
125             }
126
127             return null;
128         }
129
130         private Assembly OnResolving(AssemblyLoadContext context, AssemblyName assemblyName)
131         {
132             return Resolve(assemblyName);
133         }
134     }
135 }