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