Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / class / corlib / System / AppDomainSetup.cs
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)
10 //
11 // Known Problems:
12 //      Fix serialization compatibility with MS.NET.
13 //
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.
32 //
33
34 using System.Collections.Generic;
35 using System.IO;
36 using System.Runtime.CompilerServices;
37 using System.Runtime.InteropServices;
38 using System.Security;
39 using System.Security.Permissions;
40 using System.Runtime.Serialization.Formatters.Binary;
41
42 using System.Runtime.Hosting;
43 using System.Security.Policy;
44
45 namespace System
46 {
47         [Serializable]
48         [ClassInterface (ClassInterfaceType.None)]
49         [ComVisible (true)]
50         [StructLayout (LayoutKind.Sequential)]
51 #if MOBILE
52         public sealed class AppDomainSetup
53 #else
54         public sealed class AppDomainSetup : IAppDomainSetup
55 #endif
56         {
57                 string application_base;
58                 string application_name;
59                 string cache_path;
60                 string configuration_file;
61                 string dynamic_base;
62                 string license_file;
63                 string private_bin_path;
64                 string private_bin_path_probe;
65                 string shadow_copy_directories;
66                 string shadow_copy_files;
67                 bool publisher_policy;
68                 private bool path_changed;
69 #if MOBILE
70                 private int loader_optimization;
71 #else
72                 private LoaderOptimization loader_optimization;
73 #endif
74                 bool disallow_binding_redirects;
75                 bool disallow_code_downloads;
76
77 #if MOBILE
78                 object _activationArguments;
79                 object domain_initializer;
80                 object application_trust;
81 #else
82                 private ActivationArguments _activationArguments;
83                 AppDomainInitializer domain_initializer;
84                 [NonSerialized]
85                 ApplicationTrust application_trust;
86 #endif
87                 string [] domain_initializer_args;
88
89                 bool disallow_appbase_probe;
90                 byte [] configuration_bytes;
91
92                 byte [] serialized_non_primitives;
93
94                 public AppDomainSetup ()
95                 {
96                 }
97
98                 internal AppDomainSetup (AppDomainSetup setup)
99                 {
100                         application_base = setup.application_base;
101                         application_name = setup.application_name;
102                         cache_path = setup.cache_path;
103                         configuration_file = setup.configuration_file;
104                         dynamic_base = setup.dynamic_base;
105                         license_file = setup.license_file;
106                         private_bin_path = setup.private_bin_path;
107                         private_bin_path_probe = setup.private_bin_path_probe;
108                         shadow_copy_directories = setup.shadow_copy_directories;
109                         shadow_copy_files = setup.shadow_copy_files;
110                         publisher_policy = setup.publisher_policy;
111                         path_changed = setup.path_changed;
112                         loader_optimization = setup.loader_optimization;
113                         disallow_binding_redirects = setup.disallow_binding_redirects;
114                         disallow_code_downloads = setup.disallow_code_downloads;
115                         _activationArguments = setup._activationArguments;
116                         domain_initializer = setup.domain_initializer;
117                         application_trust = setup.application_trust;
118                         domain_initializer_args = setup.domain_initializer_args;
119                         disallow_appbase_probe = setup.disallow_appbase_probe;
120                         configuration_bytes = setup.configuration_bytes;
121                 }
122
123                 public AppDomainSetup (ActivationArguments activationArguments)
124                 {
125                         _activationArguments = activationArguments;
126                 }
127
128                 public AppDomainSetup (ActivationContext activationContext)
129                 {
130                         _activationArguments = new ActivationArguments (activationContext);
131                 }
132
133                 static string GetAppBase (string appBase)
134                 {
135                         if (appBase == null)
136                                 return null;
137
138                         int len = appBase.Length;
139                         if (len >= 8 && appBase.ToLower ().StartsWith ("file://")) {
140                                 appBase = appBase.Substring (7);
141                                 if (Path.DirectorySeparatorChar != '/')
142                                         appBase = appBase.Replace ('/', Path.DirectorySeparatorChar);
143                         }
144                         appBase = Path.GetFullPath (appBase);
145
146                         if (Path.DirectorySeparatorChar != '/') {
147                                 bool isExtendedPath = appBase.StartsWith (@"\\?\", StringComparison.Ordinal);
148                                 if (appBase.IndexOf (':', isExtendedPath ? 6 : 2) != -1) {
149                                         throw new NotSupportedException ("The given path's format is not supported.");
150                                 }
151                         }
152
153                         // validate the path
154                         string dir = Path.GetDirectoryName (appBase);
155                         if ((dir != null) && (dir.LastIndexOfAny (Path.GetInvalidPathChars ()) >= 0)) {
156                                 string msg = String.Format (Locale.GetText ("Invalid path characters in path: '{0}'"), appBase);
157                                 throw new ArgumentException (msg, "appBase");
158                         }
159
160                         string fname = Path.GetFileName (appBase);
161                         if ((fname != null) && (fname.LastIndexOfAny (Path.GetInvalidFileNameChars ()) >= 0)) {
162                                 string msg = String.Format (Locale.GetText ("Invalid filename characters in path: '{0}'"), appBase);
163                                 throw new ArgumentException (msg, "appBase");
164                         }
165
166                         return appBase;
167                 }
168
169                 public string ApplicationBase {
170                         get { return GetAppBase (application_base); }
171                         set { application_base = value; } 
172                 }
173
174                 public string ApplicationName {
175                         get {
176                                 return application_name;
177                         }
178                         set {
179                                 application_name = value;
180                         }
181                 }
182
183                 public string CachePath {
184                         get {
185                                 return cache_path;
186                         }
187                         set {
188                                 cache_path = value;
189                         }
190                 }
191
192                 public string ConfigurationFile {
193                         get {
194                                 if (configuration_file == null)
195                                         return null;
196                                 if (Path.IsPathRooted(configuration_file))
197                                         return configuration_file;
198                                 if (ApplicationBase == null)
199                                         throw new MemberAccessException("The ApplicationBase must be set before retrieving this property.");
200                                 return Path.Combine(ApplicationBase, configuration_file);
201                         }
202                         set {
203                                 configuration_file = value;
204                         }
205                 }
206
207                 public bool DisallowPublisherPolicy {
208                         get {
209                                 return publisher_policy;
210                         }
211                         set {
212                                 publisher_policy = value;
213                         }
214                 }
215
216                 public string DynamicBase {
217                         get {
218                                 if (dynamic_base == null)
219                                         return null;
220
221                                 if (Path.IsPathRooted (dynamic_base))
222                                         return dynamic_base;
223
224                                 if (ApplicationBase == null)
225                                         throw new MemberAccessException ("The ApplicationBase must be set before retrieving this property.");
226                                 
227                                 return Path.Combine (ApplicationBase, dynamic_base);
228                         }
229                         set {
230                                 if (application_name == null)
231                                         throw new MemberAccessException ("ApplicationName must be set before the DynamicBase can be set.");
232                                 uint id = (uint) application_name.GetHashCode ();
233                                 dynamic_base = Path.Combine (value, id.ToString("x"));
234                         }
235                 }
236
237                 public string LicenseFile {
238                         get {
239                                 return license_file;
240                         }
241                         set {
242                                 license_file = value;
243                         }
244                 }
245
246                 [MonoLimitation ("In Mono this is controlled by the --share-code flag")]
247                 public LoaderOptimization LoaderOptimization {
248                         get {
249                                 return (LoaderOptimization)loader_optimization;
250                         }
251                         set {
252 #if MOBILE
253                                 loader_optimization = (int)value;
254 #else
255                                 loader_optimization = value;
256 #endif
257                         }
258                 }
259
260                 public string PrivateBinPath {
261                         get {
262                                 return private_bin_path;
263                         }
264                         set {
265                                 private_bin_path = value;
266                                 path_changed = true;
267                         }
268                 }
269
270                 public string PrivateBinPathProbe {
271                         get {
272                                 return private_bin_path_probe;
273                         }
274                         set {
275                                 private_bin_path_probe = value;
276                                 path_changed = true;
277                         }
278                 }
279
280                 public string ShadowCopyDirectories {
281                         get {
282                                 return shadow_copy_directories;
283                         }
284                         set {
285                                 shadow_copy_directories = value;
286                         }
287                 }
288
289                 public string ShadowCopyFiles {
290                         get {
291                                 return shadow_copy_files;
292                         }
293                         set {
294                                 shadow_copy_files = value;
295                         }
296                 }
297
298                 public bool DisallowBindingRedirects {
299                         get {
300                                 return disallow_binding_redirects;
301                         }
302                         set {
303                                 disallow_binding_redirects = value;
304                         }
305                 }
306
307                 public bool DisallowCodeDownload {
308                         get {
309                                 return disallow_code_downloads;
310                         }
311                         set {
312                                 disallow_code_downloads = value;
313                         }
314                 }
315
316                 public string TargetFrameworkName { get; set; }
317
318                 public ActivationArguments ActivationArguments {
319                         get {
320                                 if (_activationArguments != null)
321                                         return (ActivationArguments)_activationArguments;
322                                 DeserializeNonPrimitives ();
323                                 return (ActivationArguments)_activationArguments;
324                         }
325                         set { _activationArguments = value; }
326                 }
327
328 #if MONO_FEATURE_MULTIPLE_APPDOMAINS
329                 [MonoLimitation ("it needs to be invoked within the created domain")]
330                 public AppDomainInitializer AppDomainInitializer {
331                         get {
332                                 if (domain_initializer != null)
333                                         return (AppDomainInitializer)domain_initializer;
334                                 DeserializeNonPrimitives ();
335                                 return (AppDomainInitializer)domain_initializer;
336                         }
337                         set { domain_initializer = value; }
338                 }
339 #else
340                 [Obsolete ("AppDomainSetup.AppDomainInitializer is not supported on this platform.", true)]
341                 public AppDomainInitializer AppDomainInitializer {
342                         get { throw new PlatformNotSupportedException ("AppDomainSetup.AppDomainInitializer is not supported on this platform."); }
343                         set { throw new PlatformNotSupportedException ("AppDomainSetup.AppDomainInitializer is not supported on this platform."); }
344                 }
345 #endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
346
347
348                 [MonoLimitation ("it needs to be used to invoke the initializer within the created domain")]
349                 public string [] AppDomainInitializerArguments {
350                         get { return domain_initializer_args; }
351                         set { domain_initializer_args = value; }
352                 }
353
354                 [MonoNotSupported ("This property exists but not considered.")]
355                 public ApplicationTrust ApplicationTrust {
356                         get {
357                                 if (application_trust != null)
358                                         return (ApplicationTrust)application_trust;
359                                 DeserializeNonPrimitives ();
360                                 if (application_trust == null)
361                                         application_trust = new ApplicationTrust ();
362                                 return (ApplicationTrust)application_trust;
363                         }
364                         set { application_trust = value; }
365                 }
366
367                 [MonoNotSupported ("This property exists but not considered.")]
368                 public bool DisallowApplicationBaseProbing {
369                         get { return disallow_appbase_probe; }
370                         set { disallow_appbase_probe = value; }
371                 }
372
373                 [MonoNotSupported ("This method exists but not considered.")]
374                 public byte [] GetConfigurationBytes ()
375                 {
376                         return configuration_bytes != null ? configuration_bytes.Clone () as byte [] : null;
377                 }
378
379                 [MonoNotSupported ("This method exists but not considered.")]
380                 public void SetConfigurationBytes (byte [] value)
381                 {
382                         configuration_bytes = value;
383                 }
384
385                 private void DeserializeNonPrimitives ()
386                 {
387                         lock (this) {
388                                 if (serialized_non_primitives == null)
389                                         return;
390
391                                 BinaryFormatter bf = new BinaryFormatter ();
392                                 MemoryStream ms = new MemoryStream (serialized_non_primitives);
393
394                                 object [] arr = (object []) bf.Deserialize (ms);
395
396                                 _activationArguments = (ActivationArguments) arr [0];
397 #if MONO_FEATURE_MULTIPLE_APPDOMAINS
398                                 domain_initializer = (AppDomainInitializer) arr [1];
399 #endif
400                                 application_trust = (ApplicationTrust) arr [2];
401
402                                 serialized_non_primitives = null;
403                         }
404                 }
405
406                 internal void SerializeNonPrimitives ()
407                 {
408                         object [] arr = new object [3];
409
410                         arr [0] = _activationArguments;
411                         arr [1] = domain_initializer;
412                         arr [2] = application_trust;
413
414                         BinaryFormatter bf = new BinaryFormatter ();
415                         MemoryStream ms = new MemoryStream ();
416
417                         bf.Serialize (ms, arr);
418
419                         serialized_non_primitives = ms.ToArray ();
420                 }
421
422                 [MonoTODO ("not implemented, does not throw because it's used in testing moonlight")]
423                 public void SetCompatibilitySwitches (IEnumerable<string> switches)
424                 {
425                 }
426         }
427 }