[corlib] Improve file:// url handling in AppDomainSetup. (#16161)
[mono-project.git] / mcs / class / corlib / System / AppDomainSetup.cs
blob7aea11883d615a938f9844b49b399579872426b2
1 //
2 // System.AppDomainSetup.cs
3 //
4 // Authors:
5 // Dietmar Maurer (dietmar@ximian.com)
6 // Sebastien Pouliot <sebastien@ximian.com>
7 //
8 // (C) 2001 Ximian, Inc. http://www.ximian.com
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 // Known Problems:
12 // Fix serialization compatibility with MS.NET.
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Globalization;
35 using System.Collections.Generic;
36 using System.IO;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
39 using System.Security;
40 using System.Security.Permissions;
41 using System.Runtime.Serialization.Formatters.Binary;
43 using System.Runtime.Hosting;
44 using System.Security.Policy;
46 namespace System
48 [Serializable]
49 [ClassInterface (ClassInterfaceType.None)]
50 [ComVisible (true)]
51 [StructLayout (LayoutKind.Sequential)]
52 #if MOBILE
53 public sealed class AppDomainSetup
54 #else
55 public sealed class AppDomainSetup : IAppDomainSetup
56 #endif
58 string application_base;
59 string application_name;
60 string cache_path;
61 string configuration_file;
62 string dynamic_base;
63 string license_file;
64 string private_bin_path;
65 string private_bin_path_probe;
66 string shadow_copy_directories;
67 string shadow_copy_files;
68 bool publisher_policy;
69 private bool path_changed;
70 #if MOBILE
71 private int loader_optimization;
72 #else
73 private LoaderOptimization loader_optimization;
74 #endif
75 bool disallow_binding_redirects;
76 bool disallow_code_downloads;
78 #if MOBILE
79 object _activationArguments;
80 object domain_initializer;
81 object application_trust;
82 #else
83 private ActivationArguments _activationArguments;
84 AppDomainInitializer domain_initializer;
85 [NonSerialized]
86 ApplicationTrust application_trust;
87 #endif
88 string [] domain_initializer_args;
90 bool disallow_appbase_probe;
91 byte [] configuration_bytes;
93 byte [] serialized_non_primitives;
95 string manager_assembly;
96 string manager_type;
97 string [] partial_visible_assemblies;
99 public AppDomainSetup ()
103 internal AppDomainSetup (AppDomainSetup setup)
105 application_base = setup.application_base;
106 application_name = setup.application_name;
107 cache_path = setup.cache_path;
108 configuration_file = setup.configuration_file;
109 dynamic_base = setup.dynamic_base;
110 license_file = setup.license_file;
111 private_bin_path = setup.private_bin_path;
112 private_bin_path_probe = setup.private_bin_path_probe;
113 shadow_copy_directories = setup.shadow_copy_directories;
114 shadow_copy_files = setup.shadow_copy_files;
115 publisher_policy = setup.publisher_policy;
116 path_changed = setup.path_changed;
117 loader_optimization = setup.loader_optimization;
118 disallow_binding_redirects = setup.disallow_binding_redirects;
119 disallow_code_downloads = setup.disallow_code_downloads;
120 _activationArguments = setup._activationArguments;
121 domain_initializer = setup.domain_initializer;
122 application_trust = setup.application_trust;
123 domain_initializer_args = setup.domain_initializer_args;
124 disallow_appbase_probe = setup.disallow_appbase_probe;
125 configuration_bytes = setup.configuration_bytes;
126 manager_assembly = setup.manager_assembly;
127 manager_type = setup.manager_type;
128 partial_visible_assemblies = setup.partial_visible_assemblies;
131 public AppDomainSetup (ActivationArguments activationArguments)
133 _activationArguments = activationArguments;
136 public AppDomainSetup (ActivationContext activationContext)
138 _activationArguments = new ActivationArguments (activationContext);
141 static string GetAppBase (string appBase)
143 if (appBase == null)
144 return null;
146 if (appBase.StartsWith ("file://", StringComparison.OrdinalIgnoreCase)) {
147 appBase = new Mono.Security.Uri (appBase).LocalPath;
148 if (Path.DirectorySeparatorChar != '/')
149 appBase = appBase.Replace ('/', Path.DirectorySeparatorChar);
151 appBase = Path.GetFullPath (appBase);
153 if (Path.DirectorySeparatorChar != '/') {
154 bool isExtendedPath = appBase.StartsWith (@"\\?\", StringComparison.Ordinal);
155 if (appBase.IndexOf (':', isExtendedPath ? 6 : 2) != -1) {
156 throw new NotSupportedException ("The given path's format is not supported.");
160 // validate the path
161 string dir = Path.GetDirectoryName (appBase);
162 if ((dir != null) && (dir.LastIndexOfAny (Path.GetInvalidPathChars ()) >= 0)) {
163 string msg = String.Format (Locale.GetText ("Invalid path characters in path: '{0}'"), appBase);
164 throw new ArgumentException (msg, "appBase");
167 string fname = Path.GetFileName (appBase);
168 if ((fname != null) && (fname.LastIndexOfAny (Path.GetInvalidFileNameChars ()) >= 0)) {
169 string msg = String.Format (Locale.GetText ("Invalid filename characters in path: '{0}'"), appBase);
170 throw new ArgumentException (msg, "appBase");
173 return appBase;
176 public string ApplicationBase {
177 get { return GetAppBase (application_base); }
178 set { application_base = value; }
181 public string ApplicationName {
182 get {
183 return application_name;
185 set {
186 application_name = value;
190 public string CachePath {
191 get {
192 return cache_path;
194 set {
195 cache_path = value;
199 public string ConfigurationFile {
200 get {
201 if (configuration_file == null)
202 return null;
203 if (Path.IsPathRooted(configuration_file))
204 return configuration_file;
205 if (ApplicationBase == null)
206 throw new MemberAccessException("The ApplicationBase must be set before retrieving this property.");
207 return Path.Combine(ApplicationBase, configuration_file);
209 set {
210 configuration_file = value;
214 public bool DisallowPublisherPolicy {
215 get {
216 return publisher_policy;
218 set {
219 publisher_policy = value;
223 public string DynamicBase {
224 get {
225 if (dynamic_base == null)
226 return null;
228 if (Path.IsPathRooted (dynamic_base))
229 return dynamic_base;
231 if (ApplicationBase == null)
232 throw new MemberAccessException ("The ApplicationBase must be set before retrieving this property.");
234 return Path.Combine (ApplicationBase, dynamic_base);
236 set {
237 if (application_name == null)
238 throw new MemberAccessException ("ApplicationName must be set before the DynamicBase can be set.");
239 uint id = (uint) application_name.GetHashCode ();
240 dynamic_base = Path.Combine (value, id.ToString("x"));
244 public string LicenseFile {
245 get {
246 return license_file;
248 set {
249 license_file = value;
253 [MonoLimitation ("In Mono this is controlled by the --share-code flag")]
254 public LoaderOptimization LoaderOptimization {
255 get {
256 return (LoaderOptimization)loader_optimization;
258 set {
259 #if MOBILE
260 loader_optimization = (int)value;
261 #else
262 loader_optimization = value;
263 #endif
267 // AppDomainManagerAssembly, ManagerType, and PartialTrustVisibleAssemblies
268 // don't really do anything within Mono, but will help with refsrc compat.
269 public string AppDomainManagerAssembly {
270 get { return manager_assembly; }
271 set { manager_assembly = value; }
274 public string AppDomainManagerType {
275 get { return manager_type; }
276 set { manager_type = value; }
279 public string [] PartialTrustVisibleAssemblies {
280 get { return partial_visible_assemblies; }
281 set {
282 if (value != null) {
283 partial_visible_assemblies = (string [])value.Clone();
284 Array.Sort<string> (partial_visible_assemblies, StringComparer.OrdinalIgnoreCase);
286 else {
287 partial_visible_assemblies = null;
292 public string PrivateBinPath {
293 get {
294 return private_bin_path;
296 set {
297 private_bin_path = value;
298 path_changed = true;
302 public string PrivateBinPathProbe {
303 get {
304 return private_bin_path_probe;
306 set {
307 private_bin_path_probe = value;
308 path_changed = true;
312 public string ShadowCopyDirectories {
313 get {
314 return shadow_copy_directories;
316 set {
317 shadow_copy_directories = value;
321 public string ShadowCopyFiles {
322 get {
323 return shadow_copy_files;
325 set {
326 shadow_copy_files = value;
330 public bool DisallowBindingRedirects {
331 get {
332 return disallow_binding_redirects;
334 set {
335 disallow_binding_redirects = value;
339 public bool DisallowCodeDownload {
340 get {
341 return disallow_code_downloads;
343 set {
344 disallow_code_downloads = value;
348 public string TargetFrameworkName { get; set; }
350 public ActivationArguments ActivationArguments {
351 get {
352 if (_activationArguments != null)
353 return (ActivationArguments)_activationArguments;
354 DeserializeNonPrimitives ();
355 return (ActivationArguments)_activationArguments;
357 set { _activationArguments = value; }
360 #if MONO_FEATURE_MULTIPLE_APPDOMAINS
361 [MonoLimitation ("it needs to be invoked within the created domain")]
362 public AppDomainInitializer AppDomainInitializer {
363 get {
364 if (domain_initializer != null)
365 return (AppDomainInitializer)domain_initializer;
366 DeserializeNonPrimitives ();
367 return (AppDomainInitializer)domain_initializer;
369 set { domain_initializer = value; }
371 #else
372 [Obsolete ("AppDomainSetup.AppDomainInitializer is not supported on this platform.", true)]
373 public AppDomainInitializer AppDomainInitializer {
374 get { throw new PlatformNotSupportedException ("AppDomainSetup.AppDomainInitializer is not supported on this platform."); }
375 set { throw new PlatformNotSupportedException ("AppDomainSetup.AppDomainInitializer is not supported on this platform."); }
377 #endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
380 [MonoLimitation ("it needs to be used to invoke the initializer within the created domain")]
381 public string [] AppDomainInitializerArguments {
382 get { return domain_initializer_args; }
383 set { domain_initializer_args = value; }
386 [MonoNotSupported ("This property exists but not considered.")]
387 public ApplicationTrust ApplicationTrust {
388 get {
389 if (application_trust != null)
390 return (ApplicationTrust)application_trust;
391 DeserializeNonPrimitives ();
392 if (application_trust == null)
393 application_trust = new ApplicationTrust ();
394 return (ApplicationTrust)application_trust;
396 set { application_trust = value; }
399 [MonoNotSupported ("This property exists but not considered.")]
400 public bool DisallowApplicationBaseProbing {
401 get { return disallow_appbase_probe; }
402 set { disallow_appbase_probe = value; }
405 [MonoNotSupported ("This method exists but not considered.")]
406 public byte [] GetConfigurationBytes ()
408 return configuration_bytes != null ? configuration_bytes.Clone () as byte [] : null;
411 [MonoNotSupported ("This method exists but not considered.")]
412 public void SetConfigurationBytes (byte [] value)
414 configuration_bytes = value;
417 private void DeserializeNonPrimitives ()
419 lock (this) {
420 if (serialized_non_primitives == null)
421 return;
423 BinaryFormatter bf = new BinaryFormatter ();
424 MemoryStream ms = new MemoryStream (serialized_non_primitives);
426 object [] arr = (object []) bf.Deserialize (ms);
428 _activationArguments = (ActivationArguments) arr [0];
429 #if MONO_FEATURE_MULTIPLE_APPDOMAINS
430 domain_initializer = (AppDomainInitializer) arr [1];
431 #endif
432 application_trust = (ApplicationTrust) arr [2];
434 serialized_non_primitives = null;
438 internal void SerializeNonPrimitives ()
440 object [] arr = new object [3];
442 arr [0] = _activationArguments;
443 arr [1] = domain_initializer;
444 arr [2] = application_trust;
446 BinaryFormatter bf = new BinaryFormatter ();
447 MemoryStream ms = new MemoryStream ();
449 bf.Serialize (ms, arr);
451 serialized_non_primitives = ms.ToArray ();
454 [MonoTODO ("not implemented, does not throw because it's used in testing moonlight")]
455 public void SetCompatibilitySwitches (IEnumerable<string> switches)