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