Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / class / referencesource / mscorlib / system / security / readonlypermissionset.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // <OWNER>Microsoft</OWNER>
7 //
8
9 using System;
10 using System.Collections;
11 using System.Diagnostics.Contracts;
12 using System.Runtime.Serialization;
13
14 namespace System.Security
15 {
16     /// <summary>
17     ///     Read only permission sets are created from explicit XML and cannot be modified after creation time.
18     ///     This allows us to round trip the permission set to the same XML that it was originally created
19     ///     from - which allows permission sets to be created from XML representing a permission set in a
20     ///     previous version of the framework to be deserialized on the current version while still
21     ///     serializing back to XML that makes sense on the original framework version.
22     ///     
23     ///     Note that while we protect against modifications of the permission set itself (such as adding or
24     ///     removing permissions), we do not make any attempt to guard against modification to the permissions
25     ///     which are members of the set.  Permission accesor APIs always return a copy of the permission in
26     ///     question, although it may be mutable depending upon the permission class.  If it is mutable, users
27     ///     will only be modifing a copy of the permission, and not modifying the state of the
28     ///     ReadOnlyPermissionSet.
29     /// </summary>
30     [Serializable]
31     public sealed class ReadOnlyPermissionSet : PermissionSet
32     {
33         private SecurityElement m_originXml;
34
35         [NonSerialized]
36         private bool m_deserializing;
37
38         public ReadOnlyPermissionSet(SecurityElement permissionSetXml)
39         {
40             if (permissionSetXml == null)
41                 throw new ArgumentNullException("permissionSetXml");
42
43             m_originXml = permissionSetXml.Copy();
44             base.FromXml(m_originXml);
45         }
46
47         [OnDeserializing]
48         private void OnDeserializing(StreamingContext ctx)
49         {
50             m_deserializing = true;
51         }
52
53         [OnDeserialized]
54         private void OnDeserialized(StreamingContext ctx)
55         {
56             m_deserializing = false;
57         }
58
59         public override bool IsReadOnly
60         {
61             get { return true; }
62         }
63
64         public override PermissionSet Copy()
65         {
66             return new ReadOnlyPermissionSet(m_originXml);
67         }
68
69         public override SecurityElement ToXml()
70         {
71             return m_originXml.Copy();
72         }
73
74         //
75         // Permission access methods - since modification to a permission would result in modifying the
76         // underlying permission set, we always ensure that a copy of the permission is returned rather than
77         // the permission itself.
78         //
79
80         protected override IEnumerator GetEnumeratorImpl()
81         {
82             return new ReadOnlyPermissionSetEnumerator(base.GetEnumeratorImpl());
83         }
84
85         protected override IPermission GetPermissionImpl(Type permClass)
86         {
87             IPermission permission = base.GetPermissionImpl(permClass);
88             return permission != null ? permission.Copy() : null;
89         }
90
91         //
92         // Permission set mutation methods - all of these simply reject the attempt to modify the permission
93         // set by throwing an InvalidOperationException
94         //
95
96         protected override IPermission AddPermissionImpl(IPermission perm)
97         {
98             throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ModifyROPermSet"));
99         }
100
101         public override void FromXml(SecurityElement et)
102         {
103             // PermissionSet uses FromXml when it deserializes itself - so if we're deserializing, let
104             // the base type recreate its state, otherwise it is invalid to modify a read only permission set
105             // with a FromXml call.
106             if (m_deserializing)
107             {
108                 base.FromXml(et);
109             }
110             else
111             {
112                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ModifyROPermSet"));
113             }
114         }
115
116         protected override IPermission RemovePermissionImpl(Type permClass)
117         {
118             throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ModifyROPermSet"));
119         }
120
121         protected override IPermission SetPermissionImpl(IPermission perm)
122         {
123             throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ModifyROPermSet"));
124         }
125     }
126
127     /// <summary>
128     ///     Class to enumerate permissions of a read only permission set - returning only copies of the
129     ///     permissions in the underlying permission set.
130     /// </summary>
131     internal sealed class ReadOnlyPermissionSetEnumerator : IEnumerator
132     {
133         private IEnumerator m_permissionSetEnumerator;
134
135         internal ReadOnlyPermissionSetEnumerator(IEnumerator permissionSetEnumerator)
136         {
137             Contract.Assert(permissionSetEnumerator != null);
138             m_permissionSetEnumerator = permissionSetEnumerator;
139         }
140
141         public object Current
142         {
143             get
144             {
145                 IPermission currentPermission = m_permissionSetEnumerator.Current as IPermission;
146                 return currentPermission != null ? currentPermission.Copy() : null;
147             }
148         }
149
150         public bool MoveNext()
151         {
152             return m_permissionSetEnumerator.MoveNext();
153         }
154
155         public void Reset()
156         {
157             m_permissionSetEnumerator.Reset();
158         }
159     }
160 }