083af5198961ff30de1459a8860855fb48bc76c6
[mono.git] / mcs / class / corlib / System.Security.Policy / CodeGroup.cs
1 //
2 // System.Security.Policy.CodeGroup
3 //
4 // Authors:
5 //      Nick Drochak (ndrochak@gol.com)
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // (C) 2001 Nick Drochak, All rights reserved.
9 // Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Collections;
32 using System.Globalization;
33 using System.Reflection;
34 using System.Runtime.InteropServices;
35 using System.Security.Permissions;
36
37 namespace System.Security.Policy {
38
39         [Serializable]
40         [ComVisible (true)]
41         public abstract class CodeGroup {
42                 PolicyStatement m_policy;
43                 IMembershipCondition m_membershipCondition;
44                 string m_description;
45                 string m_name;
46                 ArrayList m_children = new ArrayList();
47 //              PolicyLevel m_level;
48
49                 protected CodeGroup (IMembershipCondition membershipCondition, PolicyStatement policy)
50                 {
51                         if (null == membershipCondition)
52                                 throw new ArgumentNullException ("membershipCondition");
53
54                         if (policy != null)
55                                 m_policy = policy.Copy ();
56                         m_membershipCondition = membershipCondition.Copy ();
57                 }
58
59                 // for PolicyLevel (to avoid validation duplication)
60                 internal CodeGroup (SecurityElement e, PolicyLevel level) 
61                 {
62                         FromXml (e, level);
63                 }
64
65                 // abstract
66
67                 public abstract CodeGroup Copy ();
68
69                 public abstract string MergeLogic { get; }
70
71                 public abstract PolicyStatement Resolve (Evidence evidence);
72
73                 public abstract CodeGroup ResolveMatchingCodeGroups (Evidence evidence);
74
75                 // properties
76
77                 public PolicyStatement PolicyStatement {
78                         get { return m_policy; }
79                         set { m_policy = value; }
80                 }
81
82                 public string Description {
83                         get { return m_description; }
84                         set { m_description = value; }
85                 }
86
87                 public IMembershipCondition MembershipCondition  {
88                         get { return m_membershipCondition; }
89                         set {
90                                 if (null == value)
91                                         throw new ArgumentException ("value");
92                                 m_membershipCondition = value;
93                         }
94                 }
95
96                 public string Name {
97                         get { return m_name; }
98                         set { m_name = value; }
99                 }
100
101                 public IList Children {
102                         get { return m_children; }
103                         set {
104                                 if (null == value)
105                                         throw new ArgumentNullException ("value");
106                                 m_children = new ArrayList (value);
107                         }
108                 }
109
110                 public virtual string AttributeString {
111                         get {
112                                 if (null != m_policy)
113                                         return m_policy.AttributeString;
114                                 return null;
115                         }
116                 }
117
118                 public virtual string PermissionSetName {
119                         get {
120                                 if (m_policy == null)
121                                         return null;
122                                 if (m_policy.PermissionSet is Security.NamedPermissionSet)
123                                         return ((NamedPermissionSet)(m_policy.PermissionSet)).Name;
124                                 return null;
125                         }
126                 }
127
128                 public void AddChild (CodeGroup group)
129                 {
130                         if (null == group)
131                                 throw new ArgumentNullException ("group");
132
133                         m_children.Add (group.Copy ());
134                 }
135
136                 public override bool Equals (object o)
137                 {
138                         CodeGroup cg = (o as CodeGroup);
139                         if (cg == null)
140                                 return false;
141
142                         return Equals (cg, false);
143                 }
144
145                 public bool Equals (CodeGroup cg, bool compareChildren)
146                 {
147                         if (cg.Name != this.Name)
148                                 return false;
149
150                         if (cg.Description != this.Description)
151                                 return false;
152
153                         if (!cg.MembershipCondition.Equals (m_membershipCondition))
154                                 return false;
155
156                         if (compareChildren) {
157                                 int childCount = cg.Children.Count;
158                                 if (this.Children.Count != childCount)
159                                         return false;
160
161                                 for (int index = 0; index < childCount; index++) {
162                                         // not a deep compare
163                                         if (!((CodeGroup)(this.Children [index])).Equals ((CodeGroup)(cg.Children [index]), false))
164                                                 return false;
165                                 }
166                         }
167                         return true;
168                 }
169
170                 public void RemoveChild (CodeGroup group)
171                 {
172                         if (group != null)
173                                 m_children.Remove (group);
174                 }
175
176                 public override int GetHashCode ()
177                 {
178                         int hashCode = m_membershipCondition.GetHashCode ();
179                         if (m_policy != null)
180                                 hashCode += m_policy.GetHashCode ();
181                         return hashCode;
182                 }
183
184                 public void FromXml (SecurityElement e)
185                 {
186                         FromXml (e, null);
187                 }
188
189                 public void FromXml (SecurityElement e, PolicyLevel level)
190                 {
191                         if (null == e)
192                                 throw new ArgumentNullException("e");
193
194                         PermissionSet ps = null;
195                         string psetname = e.Attribute ("PermissionSetName");
196                         if ((psetname != null) && (level != null)) {
197                                 ps = level.GetNamedPermissionSet (psetname);
198                         }
199                         else {
200                                 SecurityElement pset = e.SearchForChildByTag ("PermissionSet");
201                                 if (pset != null) {
202                                         Type classType = Type.GetType (pset.Attribute ("class"));
203                                         ps = (PermissionSet) Activator.CreateInstance (classType, true);
204                                         ps.FromXml (pset);
205                                 }
206                                 else {
207                                         ps = new PermissionSet (new PermissionSet (PermissionState.None));
208                                 }
209                         }
210                         m_policy = new PolicyStatement (ps);
211
212                         m_children.Clear ();
213                         if ((e.Children != null) && (e.Children.Count > 0)) {
214                                 foreach (SecurityElement se in e.Children) {
215                                         if (se.Tag == "CodeGroup") {
216                                                 this.AddChild (CodeGroup.CreateFromXml (se, level));
217                                         }
218                                 }
219                         }
220                         
221                         m_membershipCondition = null;
222                         SecurityElement mc = e.SearchForChildByTag ("IMembershipCondition");
223                         if (mc != null) {
224                                 string className = mc.Attribute ("class");
225                                 Type classType = Type.GetType (className);
226                                 if (classType == null)
227                                         classType = Type.GetType ("System.Security.Policy." + className);
228                                 m_membershipCondition = (IMembershipCondition) Activator.CreateInstance (classType, true);
229                                 m_membershipCondition.FromXml (mc, level);
230                         }
231
232                         m_name = e.Attribute("Name");
233                         m_description = e.Attribute("Description");
234
235                         // seems like we might need this to Resolve() in subclasses
236                         //m_level = level;
237
238                         ParseXml (e, level);
239                 }
240
241                 protected virtual void ParseXml (SecurityElement e, PolicyLevel level)
242                 {
243                 }
244                 
245                 public SecurityElement ToXml ()
246                 {
247                         return ToXml (null);
248                 }
249
250                 public SecurityElement ToXml (PolicyLevel level)
251                 {
252                         SecurityElement e = new SecurityElement("CodeGroup");
253                         e.AddAttribute("class", this.GetType().AssemblyQualifiedName);
254                         e.AddAttribute("version", "1");
255
256                         if (null != Name)
257                                 e.AddAttribute("Name", Name);
258
259                         if (null != Description)
260                                 e.AddAttribute("Description", Description);
261
262                         if (null != MembershipCondition)
263                                 e.AddChild(MembershipCondition.ToXml());
264
265                         if ((PolicyStatement != null) && (PolicyStatement.PermissionSet != null))
266                                 e.AddChild (PolicyStatement.PermissionSet.ToXml ());
267
268                         foreach (CodeGroup child in Children)
269                                 e.AddChild(child.ToXml());
270
271                         CreateXml(e, level);
272                         return e;
273                 }
274                 
275                 protected virtual void CreateXml (SecurityElement element, PolicyLevel level)
276                 {
277                 }
278
279                 // internal stuff
280
281                 internal static CodeGroup CreateFromXml (SecurityElement se, PolicyLevel level) 
282                 {
283                         string fullClassName = se.Attribute ("class");
284                         string className = fullClassName;
285                         // many possible formats
286                         // a. "FirstMatchCodeGroup"
287                         // b. "System.Security.Policy.FirstMatchCodeGroup"
288                         // c. "System.Security.Policy.FirstMatchCodeGroup, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\"\r\n           version=\"1\">\r\n   <IMembershipCondition class=\"System.Security.Policy.AllMembershipCondition, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
289                         int n = className.IndexOf (",");
290                         if (n > 0) {
291                                 className = className.Substring (0, n);
292                         }
293                         n = className.LastIndexOf (".");
294                         if (n > 0)
295                                 className = className.Substring (n + 1);
296                         // much faster than calling Activator.CreateInstance
297                         switch (className) {
298                                 case "FileCodeGroup":
299                                         return new FileCodeGroup (se, level);
300                                 case "FirstMatchCodeGroup":
301                                         return new FirstMatchCodeGroup (se, level);
302                                 case "NetCodeGroup":
303                                         return new NetCodeGroup (se, level);
304                                 case "UnionCodeGroup":
305                                         return new UnionCodeGroup (se, level);
306                                 default: // unknown
307                                         Type classType = Type.GetType (fullClassName);
308                                         CodeGroup cg = (CodeGroup) Activator.CreateInstance (classType, true);
309                                         cg.FromXml (se, level);
310                                         return cg;
311                         }
312                 }
313         }
314 }