PageRenderTime 42ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/IronPython_Main/Runtime/Microsoft.Scripting/PlatformAdaptationLayer.cs

#
C# | 411 lines | 320 code | 52 blank | 39 comment | 26 complexity | 965dab1818ac8961519dd833e09ea366 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if !CLR2
  16. using System.Linq.Expressions;
  17. #else
  18. using Microsoft.Scripting.Ast;
  19. #endif
  20. using System;
  21. using System.Collections.Generic;
  22. using System.IO;
  23. using System.Reflection;
  24. using System.Runtime.InteropServices;
  25. using System.Security;
  26. using Microsoft.Scripting.Utils;
  27. using System.Runtime.CompilerServices;
  28. namespace Microsoft.Scripting {
  29. #if SILVERLIGHT
  30. public class ExitProcessException : Exception {
  31. public int ExitCode { get { return exitCode; } }
  32. int exitCode;
  33. public ExitProcessException(int exitCode) {
  34. this.exitCode = exitCode;
  35. }
  36. }
  37. #endif
  38. /// <summary>
  39. /// Abstracts system operations that are used by DLR and could potentially be platform specific.
  40. /// The host can implement its PAL to adapt DLR to the platform it is running on.
  41. /// For example, the Silverlight host adapts some file operations to work against files on the server.
  42. /// </summary>
  43. [Serializable]
  44. public class PlatformAdaptationLayer {
  45. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  46. public static readonly PlatformAdaptationLayer Default = new PlatformAdaptationLayer();
  47. public static readonly bool IsCompactFramework =
  48. Environment.OSVersion.Platform == PlatformID.WinCE ||
  49. Environment.OSVersion.Platform == PlatformID.Xbox;
  50. #if SILVERLIGHT
  51. // this dictionary is readonly after initialization:
  52. private Dictionary<string, string> _assemblyFullNames = new Dictionary<string, string>();
  53. public PlatformAdaptationLayer() {
  54. LoadSilverlightAssemblyNameMapping();
  55. }
  56. // TODO: remove the need for this
  57. private void LoadSilverlightAssemblyNameMapping() {
  58. // non-trasparent assemblies
  59. AssemblyName platformKeyVer = new AssemblyName(typeof(object).Assembly.FullName);
  60. AddAssemblyMappings(platformKeyVer,
  61. "mscorlib",
  62. "System",
  63. "System.Core",
  64. "System.Net",
  65. "System.Runtime.Serialization",
  66. "System.ServiceModel.Web",
  67. "System.Windows",
  68. "System.Windows.Browser",
  69. "System.Xml",
  70. "Microsoft.VisualBasic"
  71. );
  72. // DLR + language assemblies
  73. AssemblyName languageKeyVer = new AssemblyName(typeof(PlatformAdaptationLayer).Assembly.FullName);
  74. AddAssemblyMappings(languageKeyVer,
  75. "Microsoft.Scripting",
  76. "Microsoft.Dynamic",
  77. "Microsoft.Scripting.Core",
  78. "Microsoft.Scripting.Silverlight",
  79. "IronPython",
  80. "IronPython.Modules",
  81. "IronRuby",
  82. "IronRuby.Libraries"
  83. );
  84. // transparent assemblies => same version as mscorlib but uses transparent key (same as languages)
  85. AssemblyName transparentKeyVer = new AssemblyName(typeof(object).Assembly.FullName);
  86. transparentKeyVer.SetPublicKeyToken(languageKeyVer.GetPublicKeyToken());
  87. AddAssemblyMappings(transparentKeyVer,
  88. "System.ServiceModel",
  89. "System.ServiceModel.Syndication",
  90. "System.Windows.Controls",
  91. "System.Windows.Controls.Data",
  92. "System.Windows.Controls.Data.Design",
  93. "System.Windows.Controls.Design",
  94. "System.Windows.Controls.Extended",
  95. "System.Windows.Controls.Extended.Design",
  96. "System.Xml.Linq",
  97. "System.Xml.Serialization"
  98. );
  99. }
  100. private void AddAssemblyMappings(AssemblyName keyVersion, params string[] names) {
  101. foreach (string asm in names) {
  102. keyVersion.Name = asm;
  103. _assemblyFullNames.Add(asm.ToLower(), keyVersion.FullName);
  104. }
  105. }
  106. protected string LookupFullName(string name) {
  107. AssemblyName asm = new AssemblyName(name);
  108. if (asm.Version != null || asm.GetPublicKeyToken() != null || asm.GetPublicKey() != null) {
  109. return name;
  110. }
  111. return _assemblyFullNames.ContainsKey(name.ToLower()) ? _assemblyFullNames[name.ToLower()] : name;
  112. }
  113. #endif
  114. #region Assembly Loading
  115. public virtual Assembly LoadAssembly(string name) {
  116. #if !SILVERLIGHT
  117. return Assembly.Load(name);
  118. #else
  119. return Assembly.Load(LookupFullName(name));
  120. #endif
  121. }
  122. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFile")]
  123. public virtual Assembly LoadAssemblyFromPath(string path) {
  124. #if !SILVERLIGHT
  125. return Assembly.LoadFile(path);
  126. #else
  127. throw new NotImplementedException();
  128. #endif
  129. }
  130. public virtual void TerminateScriptExecution(int exitCode) {
  131. #if !SILVERLIGHT
  132. System.Environment.Exit(exitCode);
  133. #else
  134. throw new ExitProcessException(exitCode);
  135. #endif
  136. }
  137. #endregion
  138. #region Virtual File System
  139. private static bool IsSingleRootFileSystem {
  140. get {
  141. return Environment.OSVersion.Platform == PlatformID.Unix
  142. || Environment.OSVersion.Platform == PlatformID.MacOSX;
  143. }
  144. }
  145. public virtual StringComparer PathComparer {
  146. get {
  147. return Environment.OSVersion.Platform == PlatformID.Unix ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
  148. }
  149. }
  150. public virtual bool FileExists(string path) {
  151. #if !SILVERLIGHT
  152. return File.Exists(path);
  153. #else
  154. throw new NotImplementedException();
  155. #endif
  156. }
  157. public virtual bool DirectoryExists(string path) {
  158. #if !SILVERLIGHT
  159. return Directory.Exists(path);
  160. #else
  161. throw new NotImplementedException();
  162. #endif
  163. }
  164. // TODO: better APIs
  165. public virtual Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share) {
  166. #if !SILVERLIGHT
  167. return new FileStream(path, mode, access, share);
  168. #else
  169. throw new NotImplementedException();
  170. #endif
  171. }
  172. // TODO: better APIs
  173. public virtual Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) {
  174. #if !SILVERLIGHT
  175. return new FileStream(path, mode, access, share, bufferSize);
  176. #else
  177. throw new NotImplementedException();
  178. #endif
  179. }
  180. // TODO: better APIs
  181. public virtual Stream OpenInputFileStream(string path) {
  182. #if !SILVERLIGHT
  183. return new FileStream(path, FileMode.Open, FileAccess.Read);
  184. #else
  185. throw new NotImplementedException();
  186. #endif
  187. }
  188. // TODO: better APIs
  189. public virtual Stream OpenOutputFileStream(string path) {
  190. #if !SILVERLIGHT
  191. return new FileStream(path, FileMode.Create, FileAccess.Write);
  192. #else
  193. throw new NotImplementedException();
  194. #endif
  195. }
  196. public virtual void DeleteFile(string path, bool deleteReadOnly) {
  197. #if !SILVERLIGHT
  198. FileInfo info = new FileInfo(path);
  199. if (deleteReadOnly && info.IsReadOnly) {
  200. info.IsReadOnly = false;
  201. }
  202. info.Delete();
  203. #else
  204. throw new NotImplementedException();
  205. #endif
  206. }
  207. public string[] GetFiles(string path, string searchPattern) {
  208. return GetFileSystemEntries(path, searchPattern, true, false);
  209. }
  210. public string[] GetDirectories(string path, string searchPattern) {
  211. return GetFileSystemEntries(path, searchPattern, false, true);
  212. }
  213. public string[] GetFileSystemEntries(string path, string searchPattern) {
  214. return GetFileSystemEntries(path, searchPattern, true, true);
  215. }
  216. public virtual string[] GetFileSystemEntries(string path, string searchPattern, bool includeFiles, bool includeDirectories) {
  217. #if !SILVERLIGHT
  218. if (includeFiles && includeDirectories) {
  219. return Directory.GetFileSystemEntries(path, searchPattern);
  220. }
  221. if (includeFiles) {
  222. return Directory.GetFiles(path, searchPattern);
  223. }
  224. if (includeDirectories) {
  225. return Directory.GetDirectories(path, searchPattern);
  226. }
  227. return ArrayUtils.EmptyStrings;
  228. #else
  229. throw new NotImplementedException();
  230. #endif
  231. }
  232. /// <exception cref="ArgumentException">Invalid path.</exception>
  233. public virtual string GetFullPath(string path) {
  234. #if !SILVERLIGHT
  235. try {
  236. return Path.GetFullPath(path);
  237. } catch (Exception) {
  238. throw Error.InvalidPath();
  239. }
  240. #else
  241. throw new NotImplementedException();
  242. #endif
  243. }
  244. public virtual string CombinePaths(string path1, string path2) {
  245. return Path.Combine(path1, path2);
  246. }
  247. public virtual string GetFileName(string path) {
  248. return Path.GetFileName(path);
  249. }
  250. public virtual string GetDirectoryName(string path) {
  251. return Path.GetDirectoryName(path);
  252. }
  253. public virtual string GetExtension(string path) {
  254. return Path.GetExtension(path);
  255. }
  256. public virtual string GetFileNameWithoutExtension(string path) {
  257. return Path.GetFileNameWithoutExtension(path);
  258. }
  259. /// <exception cref="ArgumentException">Invalid path.</exception>
  260. public virtual bool IsAbsolutePath(string path) {
  261. #if !SILVERLIGHT
  262. // GetPathRoot returns either :
  263. // "" -> relative to the current dir
  264. // "\" -> relative to the drive of the current dir
  265. // "X:" -> relative to the current dir, possibly on a different drive
  266. // "X:\" -> absolute
  267. if (IsSingleRootFileSystem) {
  268. return Path.IsPathRooted(path);
  269. }
  270. var root = Path.GetPathRoot(path);
  271. return root.EndsWith(@":\") || root.EndsWith(@":/");
  272. #else
  273. throw new NotImplementedException();
  274. #endif
  275. }
  276. public virtual string CurrentDirectory {
  277. get {
  278. #if !SILVERLIGHT
  279. return Directory.GetCurrentDirectory();
  280. #else
  281. throw new NotImplementedException();
  282. #endif
  283. }
  284. set {
  285. #if !SILVERLIGHT
  286. Directory.SetCurrentDirectory(value);
  287. #else
  288. throw new NotImplementedException();
  289. #endif
  290. }
  291. }
  292. public virtual void CreateDirectory(string path) {
  293. #if !SILVERLIGHT
  294. Directory.CreateDirectory(path);
  295. #else
  296. throw new NotImplementedException();
  297. #endif
  298. }
  299. public virtual void DeleteDirectory(string path, bool recursive) {
  300. #if !SILVERLIGHT
  301. Directory.Delete(path, recursive);
  302. #else
  303. throw new NotImplementedException();
  304. #endif
  305. }
  306. public virtual void MoveFileSystemEntry(string sourcePath, string destinationPath) {
  307. #if !SILVERLIGHT
  308. Directory.Move(sourcePath, destinationPath);
  309. #else
  310. throw new NotImplementedException();
  311. #endif
  312. }
  313. #endregion
  314. #region Environmental Variables
  315. public virtual string GetEnvironmentVariable(string key) {
  316. #if !SILVERLIGHT
  317. return Environment.GetEnvironmentVariable(key);
  318. #else
  319. throw new NotImplementedException();
  320. #endif
  321. }
  322. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
  323. public virtual void SetEnvironmentVariable(string key, string value) {
  324. #if !SILVERLIGHT
  325. if (value != null && value.Length == 0) {
  326. SetEmptyEnvironmentVariable(key);
  327. } else {
  328. Environment.SetEnvironmentVariable(key, value);
  329. }
  330. #else
  331. throw new NotImplementedException();
  332. #endif
  333. }
  334. #if !SILVERLIGHT
  335. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
  336. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2149:TransparentMethodsMustNotCallNativeCodeFxCopRule")]
  337. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2140:TransparentMethodsMustNotReferenceCriticalCodeFxCopRule")]
  338. [MethodImpl(MethodImplOptions.NoInlining)]
  339. private static void SetEmptyEnvironmentVariable(string key) {
  340. // System.Environment.SetEnvironmentVariable interprets an empty value string as
  341. // deleting the environment variable. So we use the native SetEnvironmentVariable
  342. // function here which allows setting of the value to an empty string.
  343. // This will require high trust and will fail in sandboxed environments
  344. if (!NativeMethods.SetEnvironmentVariable(key, String.Empty)) {
  345. throw new ExternalException("SetEnvironmentVariable failed", Marshal.GetLastWin32Error());
  346. }
  347. }
  348. #endif
  349. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
  350. public virtual System.Collections.IDictionary GetEnvironmentVariables() {
  351. #if !SILVERLIGHT
  352. return Environment.GetEnvironmentVariables();
  353. #else
  354. throw new NotImplementedException();
  355. #endif
  356. }
  357. #endregion
  358. }
  359. }