1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
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.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Linq.Expressions;
19 using Microsoft.Scripting.Ast;
23 using System.Collections.Generic;
25 using System.Reflection;
26 using System.Runtime.InteropServices;
27 using System.Security;
28 using Microsoft.Scripting.Utils;
29 using System.Runtime.CompilerServices;
30 using System.Collections;
32 namespace Microsoft.Scripting {
35 public class ExitProcessException : Exception {
37 public int ExitCode { get { return exitCode; } }
40 public ExitProcessException(int exitCode) {
41 this.exitCode = exitCode;
47 /// Abstracts system operations that are used by DLR and could potentially be platform specific.
48 /// The host can implement its PAL to adapt DLR to the platform it is running on.
49 /// For example, the Silverlight host adapts some file operations to work against files on the server.
52 public class PlatformAdaptationLayer {
53 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
54 public static readonly PlatformAdaptationLayer Default = new PlatformAdaptationLayer();
56 public static readonly bool IsCompactFramework =
60 Environment.OSVersion.Platform == PlatformID.WinCE ||
61 Environment.OSVersion.Platform == PlatformID.Xbox;
66 // this dictionary is readonly after initialization:
67 private Dictionary<string, string> _assemblyFullNames = new Dictionary<string, string>();
69 public PlatformAdaptationLayer() {
70 LoadSilverlightAssemblyNameMapping();
73 // TODO: remove the need for this
74 private void LoadSilverlightAssemblyNameMapping() {
75 // non-trasparent assemblies
76 AssemblyName platformKeyVer = new AssemblyName(typeof(object).Assembly.FullName);
77 AddAssemblyMappings(platformKeyVer,
82 "System.Runtime.Serialization",
83 "System.ServiceModel.Web",
85 "System.Windows.Browser",
87 "Microsoft.VisualBasic"
90 // DLR + language assemblies
91 AssemblyName languageKeyVer = new AssemblyName(typeof(PlatformAdaptationLayer).Assembly.FullName);
92 AddAssemblyMappings(languageKeyVer,
93 "Microsoft.Scripting",
95 "Microsoft.Scripting.Core",
96 "Microsoft.Scripting.Silverlight",
103 // transparent assemblies => same version as mscorlib but uses transparent key (same as languages)
104 AssemblyName transparentKeyVer = new AssemblyName(typeof(object).Assembly.FullName);
105 transparentKeyVer.SetPublicKeyToken(languageKeyVer.GetPublicKeyToken());
106 AddAssemblyMappings(transparentKeyVer,
107 "System.ServiceModel",
108 "System.ServiceModel.Syndication",
109 "System.Windows.Controls",
110 "System.Windows.Controls.Data",
111 "System.Windows.Controls.Data.Design",
112 "System.Windows.Controls.Design",
113 "System.Windows.Controls.Extended",
114 "System.Windows.Controls.Extended.Design",
116 "System.Xml.Serialization"
120 private void AddAssemblyMappings(AssemblyName keyVersion, params string[] names) {
121 foreach (string asm in names) {
122 keyVersion.Name = asm;
123 _assemblyFullNames.Add(asm.ToLower(), keyVersion.FullName);
127 protected string LookupFullName(string name) {
128 AssemblyName asm = new AssemblyName(name);
129 if (asm.Version != null || asm.GetPublicKeyToken() != null || asm.GetPublicKey() != null) {
132 return _assemblyFullNames.ContainsKey(name.ToLower()) ? _assemblyFullNames[name.ToLower()] : name;
135 #region Assembly Loading
137 public virtual Assembly LoadAssembly(string name) {
139 throw new NotImplementedException();
141 return Assembly.Load(name);
143 return Assembly.Load(LookupFullName(name));
147 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFile")]
148 public virtual Assembly LoadAssemblyFromPath(string path) {
149 #if FEATURE_FILESYSTEM
150 return Assembly.LoadFile(path);
152 throw new NotImplementedException();
156 public virtual void TerminateScriptExecution(int exitCode) {
158 System.Environment.Exit(exitCode);
160 throw new ExitProcessException(exitCode);
166 #region Virtual File System
168 public virtual bool IsSingleRootFileSystem {
170 #if FEATURE_FILESYSTEM
171 return Environment.OSVersion.Platform == PlatformID.Unix
172 || Environment.OSVersion.Platform == PlatformID.MacOSX;
181 public virtual StringComparer PathComparer {
183 #if FEATURE_FILESYSTEM
184 return Environment.OSVersion.Platform == PlatformID.Unix ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
186 return StringComparer.OrdinalIgnoreCase;
191 public virtual bool FileExists(string path) {
192 #if FEATURE_FILESYSTEM
193 return File.Exists(path);
195 throw new NotImplementedException();
199 public virtual bool DirectoryExists(string path) {
200 #if FEATURE_FILESYSTEM
201 return Directory.Exists(path);
203 throw new NotImplementedException();
209 public virtual Stream OpenFileStream(string path, FileMode mode = FileMode.OpenOrCreate, FileAccess access = FileAccess.ReadWrite, FileShare share = FileShare.Read, int bufferSize = 8192) {
210 #if FEATURE_FILESYSTEM
211 if (string.Equals("nul", path, StringComparison.InvariantCultureIgnoreCase)) {
214 return new FileStream(path, mode, access, share, bufferSize);
216 throw new NotImplementedException();
221 public virtual Stream OpenInputFileStream(string path, FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read, FileShare share = FileShare.Read, int bufferSize = 8192) {
222 return OpenFileStream(path, mode, access, share, bufferSize);
226 public virtual Stream OpenOutputFileStream(string path) {
227 return OpenFileStream(path, FileMode.Create, FileAccess.Write);
230 public virtual Stream OpenFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) {
231 #if FEATURE_FILESYSTEM
232 if (string.Equals("nul", path, StringComparison.InvariantCultureIgnoreCase)) {
235 return new FileStream(path, mode, access, share, bufferSize);
237 throw new NotImplementedException();
242 public virtual Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share) {
243 return OpenFileStream(path, mode, access, share, 8912);
247 public virtual Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) {
248 return OpenFileStream(path, mode, access, share, bufferSize);
252 public virtual Stream OpenInputFileStream(string path) {
253 return OpenFileStream(path, FileMode.Open, FileAccess.Read, FileShare.None, 8912);
257 public virtual Stream OpenOutputFileStream(string path) {
258 return OpenFileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 8912);
262 public virtual void DeleteFile(string path, bool deleteReadOnly) {
263 #if FEATURE_FILESYSTEM
264 FileInfo info = new FileInfo(path);
266 if (deleteReadOnly && info.IsReadOnly) {
267 info.IsReadOnly = false;
272 throw new NotImplementedException();
276 public string[] GetFiles(string path, string searchPattern) {
277 return GetFileSystemEntries(path, searchPattern, true, false);
280 public string[] GetDirectories(string path, string searchPattern) {
281 return GetFileSystemEntries(path, searchPattern, false, true);
284 public string[] GetFileSystemEntries(string path, string searchPattern) {
285 return GetFileSystemEntries(path, searchPattern, true, true);
288 public virtual string[] GetFileSystemEntries(string path, string searchPattern, bool includeFiles, bool includeDirectories) {
289 #if FEATURE_FILESYSTEM
290 if (includeFiles && includeDirectories) {
291 return Directory.GetFileSystemEntries(path, searchPattern);
294 return Directory.GetFiles(path, searchPattern);
296 if (includeDirectories) {
297 return Directory.GetDirectories(path, searchPattern);
299 return ArrayUtils.EmptyStrings;
301 throw new NotImplementedException();
305 /// <exception cref="ArgumentException">Invalid path.</exception>
306 public virtual string GetFullPath(string path) {
307 #if FEATURE_FILESYSTEM
309 return Path.GetFullPath(path);
310 } catch (Exception) {
311 throw Error.InvalidPath();
314 throw new NotImplementedException();
318 public virtual string CombinePaths(string path1, string path2) {
319 return Path.Combine(path1, path2);
322 public virtual string GetFileName(string path) {
323 return Path.GetFileName(path);
326 public virtual string GetDirectoryName(string path) {
327 return Path.GetDirectoryName(path);
330 public virtual string GetExtension(string path) {
331 return Path.GetExtension(path);
334 public virtual string GetFileNameWithoutExtension(string path) {
335 return Path.GetFileNameWithoutExtension(path);
338 /// <exception cref="ArgumentException">Invalid path.</exception>
339 public virtual bool IsAbsolutePath(string path) {
340 if (String.IsNullOrEmpty(path)) {
344 // no drives, no UNC:
345 if (IsSingleRootFileSystem) {
346 return IsDirectorySeparator(path[0]);
349 if (IsDirectorySeparator(path[0])) {
351 return path.Length > 1 && IsDirectorySeparator(path[1]);
354 if (path.Length > 2 && path[1] == ':' && IsDirectorySeparator(path[2])) {
361 #if FEATURE_FILESYSTEM
362 private bool IsDirectorySeparator(char c) {
363 return c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar;
366 private bool IsDirectorySeparator(char c) {
367 return c == '\\' || c == '/';
371 public virtual string CurrentDirectory {
373 #if FEATURE_FILESYSTEM
374 return Directory.GetCurrentDirectory();
376 throw new NotImplementedException();
380 #if FEATURE_FILESYSTEM
381 Directory.SetCurrentDirectory(value);
383 throw new NotImplementedException();
388 public virtual void CreateDirectory(string path) {
389 #if FEATURE_FILESYSTEM
390 Directory.CreateDirectory(path);
392 throw new NotImplementedException();
396 public virtual void DeleteDirectory(string path, bool recursive) {
397 #if FEATURE_FILESYSTEM
398 Directory.Delete(path, recursive);
400 throw new NotImplementedException();
404 public virtual void MoveFileSystemEntry(string sourcePath, string destinationPath) {
405 #if FEATURE_FILESYSTEM
406 Directory.Move(sourcePath, destinationPath);
408 throw new NotImplementedException();
414 #region Environmental Variables
416 public virtual string GetEnvironmentVariable(string key) {
418 return Environment.GetEnvironmentVariable(key);
420 throw new NotImplementedException();
424 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
425 public virtual void SetEnvironmentVariable(string key, string value) {
427 if (value != null && value.Length == 0) {
428 SetEmptyEnvironmentVariable(key);
430 Environment.SetEnvironmentVariable(key, value);
433 throw new NotImplementedException();
438 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
439 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2149:TransparentMethodsMustNotCallNativeCodeFxCopRule")]
440 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2140:TransparentMethodsMustNotReferenceCriticalCodeFxCopRule")]
441 [MethodImpl(MethodImplOptions.NoInlining)]
442 private static void SetEmptyEnvironmentVariable(string key) {
443 // System.Environment.SetEnvironmentVariable interprets an empty value string as
444 // deleting the environment variable. So we use the native SetEnvironmentVariable
445 // function here which allows setting of the value to an empty string.
446 // This will require high trust and will fail in sandboxed environments
447 if (!NativeMethods.SetEnvironmentVariable(key, String.Empty)) {
448 throw new ExternalException("SetEnvironmentVariable failed", Marshal.GetLastWin32Error());
453 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
454 public virtual Dictionary<string, string> GetEnvironmentVariables() {
456 var result = new Dictionary<string, string>();
458 foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
460 result.Add((string)entry.Key, (string)entry.Value);
465 throw new NotImplementedException();