* roottypes.cs: Rename from tree.cs.
[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 #if NET_2_0
41         [ComVisible (true)]
42 #endif
43         public abstract class CodeGroup {
44                 PolicyStatement m_policy;
45                 IMembershipCondition m_membershipCondition;
46                 string m_description;
47                 string m_name;
48                 ArrayList m_children = new ArrayList();
49                 PolicyLevel m_level;
50
51 #if NET_2_0
52                 protected CodeGroup (IMembershipCondition membershipCondition, PolicyStatement policy)
53 #else
54                 public CodeGroup (IMembershipCondition membershipCondition, PolicyStatement policy)
55 #endif
56                 {
57                         if (null == membershipCondition)
58                                 throw new ArgumentNullException ("membershipCondition");
59
60                         if (policy != null)
61                                 m_policy = policy.Copy ();
62                         m_membershipCondition = membershipCondition.Copy ();
63                 }
64
65                 // for PolicyLevel (to avoid validation duplication)
66                 internal CodeGroup (SecurityElement e, PolicyLevel level) 
67                 {
68                         FromXml (e, level);
69                 }
70
71                 // abstract
72
73                 public abstract CodeGroup Copy ();
74
75                 public abstract string MergeLogic { get; }
76
77                 public abstract PolicyStatement Resolve (Evidence evidence);
78
79                 public abstract CodeGroup ResolveMatchingCodeGroups (Evidence evidence);
80
81                 // properties
82
83                 public PolicyStatement PolicyStatement {
84                         get { return m_policy; }
85                         set { m_policy = value; }
86                 }
87
88                 public string Description {
89                         get { return m_description; }
90                         set { m_description = value; }
91                 }
92
93                 public IMembershipCondition MembershipCondition  {
94                         get { return m_membershipCondition; }
95                         set {
96                                 if (null == value)
97                                         throw new ArgumentException ("value");
98                                 m_membershipCondition = value;
99                         }
100                 }
101
102                 public string Name {
103                         get { return m_name; }
104                         set { m_name = value; }
105                 }
106
107                 public IList Children {
108                         get { return m_children; }
109                         set {
110                                 if (null == value)
111                                         throw new ArgumentNullException ("value");
112                                 m_children = new ArrayList (value);
113                         }
114                 }
115
116                 public virtual string AttributeString {
117                         get {
118                                 if (null != m_policy)
119                                         return m_policy.AttributeString;
120                                 return null;
121                         }
122                 }
123
124                 public virtual string PermissionSetName {
125                         get {
126                                 if (m_policy == null)
127                                         return null;
128                                 if (m_policy.PermissionSet is Security.NamedPermissionSet)
129                                         return ((NamedPermissionSet)(m_policy.PermissionSet)).Name;
130                                 return null;
131                         }
132                 }
133
134                 public void AddChild (CodeGroup group)
135                 {
136                         if (null == group)
137                                 throw new ArgumentNullException ("group");
138
139                         m_children.Add (group.Copy ());
140                 }
141
142                 public override bool Equals (object o)
143                 {
144                         CodeGroup cg = (o as CodeGroup);
145                         if (cg == null)
146                                 return false;
147
148                         return Equals (cg, false);
149                 }
150
151                 public bool Equals (CodeGroup cg, bool compareChildren)
152                 {
153                         if (cg.Name != this.Name)
154                                 return false;
155
156                         if (cg.Description != this.Description)
157                                 return false;
158
159                         if (!cg.MembershipCondition.Equals (m_membershipCondition))
160                                 return false;
161
162                         if (compareChildren) {
163                                 int childCount = cg.Children.Count;
164                                 if (this.Children.Count != childCount)
165                                         return false;
166
167                                 for (int index = 0; index < childCount; index++) {
168                                         // not a deep compare
169                                         if (!((CodeGroup)(this.Children [index])).Equals ((CodeGroup)(cg.Children [index]), false))
170                                                 return false;
171                                 }
172                         }
173                         return true;
174                 }
175
176                 public void RemoveChild (CodeGroup group)
177                 {
178                         if (group != null)
179                                 m_children.Remove (group);
180                 }
181
182                 public override int GetHashCode ()
183                 {
184                         int hashCode = m_membershipCondition.GetHashCode ();
185                         if (m_policy != null)
186                                 hashCode += m_policy.GetHashCode ();
187                         return hashCode;
188                 }
189
190                 public void FromXml (SecurityElement e)
191                 {
192                         FromXml (e, null);
193                 }
194
195                 public void FromXml (SecurityElement e, PolicyLevel level)
196                 {
197                         if (null == e)
198                                 throw new ArgumentNullException("e");
199
200                         PermissionSet ps = null;
201                         string psetname = e.Attribute ("PermissionSetName");
202                         if ((psetname != null) && (level != null)) {
203                                 ps = level.GetNamedPermissionSet (psetname);
204                         }
205                         else {
206                                 SecurityElement pset = e.SearchForChildByTag ("PermissionSet");
207                                 if (pset != null) {
208                                         Type classType = Type.GetType (pset.Attribute ("class"));
209                                         ps = (PermissionSet) Activator.CreateInstance (classType, true);
210                                         ps.FromXml (pset);
211                                 }
212                                 else {
213                                         ps = new PermissionSet (new PermissionSet (PermissionState.None));
214                                 }
215                         }
216                         m_policy = new PolicyStatement (ps);
217
218                         m_children.Clear ();
219                         if ((e.Children != null) && (e.Children.Count > 0)) {
220                                 foreach (SecurityElement se in e.Children) {
221                                         if (se.Tag == "CodeGroup") {
222                                                 this.AddChild (CodeGroup.CreateFromXml (se, level));
223                                         }
224                                 }
225                         }
226                         
227                         m_membershipCondition = null;
228                         SecurityElement mc = e.SearchForChildByTag ("IMembershipCondition");
229                         if (mc != null) {
230                                 string className = mc.Attribute ("class");
231                                 Type classType = Type.GetType (className);
232                                 if (classType == null)
233                                         classType = Type.GetType ("System.Security.Policy." + className);
234                                 m_membershipCondition = (IMembershipCondition) Activator.CreateInstance (classType, true);
235                                 m_membershipCondition.FromXml (mc, level);
236                         }
237
238                         m_name = e.Attribute("Name");
239                         m_description = e.Attribute("Description");
240
241                         // seems like we might need this to Resolve() in subclasses
242                         m_level = level;
243
244                         ParseXml (e, level);
245                 }
246
247                 protected virtual void ParseXml (SecurityElement e, PolicyLevel level)
248                 {
249                 }
250                 
251                 public SecurityElement ToXml ()
252                 {
253                         return ToXml (null);
254                 }
255
256                 public SecurityElement ToXml (PolicyLevel level)
257                 {
258                         SecurityElement e = new SecurityElement("CodeGroup");
259                         e.AddAttribute("class", this.GetType().AssemblyQualifiedName);
260                         e.AddAttribute("version", "1");
261
262                         if (null != Name)
263                                 e.AddAttribute("Name", Name);
264
265                         if (null != Description)
266                                 e.AddAttribute("Description", Description);
267
268                         if (null != MembershipCondition)
269                                 e.AddChild(MembershipCondition.ToXml());
270
271                         if ((PolicyStatement != null) && (PolicyStatement.PermissionSet != null))
272                                 e.AddChild (PolicyStatement.PermissionSet.ToXml ());
273
274                         foreach (CodeGroup child in Children)
275                                 e.AddChild(child.ToXml());
276
277                         CreateXml(e, level);
278                         return e;
279                 }
280                 
281                 protected virtual void CreateXml (SecurityElement element, PolicyLevel level)
282                 {
283                 }
284
285                 // internal stuff
286
287                 internal static CodeGroup CreateFromXml (SecurityElement se, PolicyLevel level) 
288                 {
289                         string fullClassName = se.Attribute ("class");
290                         string className = fullClassName;
291                         // many possible formats
292                         // a. "FirstMatchCodeGroup"
293                         // b. "System.Security.Policy.FirstMatchCodeGroup"
294                         // 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"
295                         int n = className.IndexOf (",");
296                         if (n > 0) {
297                                 className = className.Substring (0, n);
298                         }
299                         n = className.LastIndexOf (".");
300                         if (n > 0)
301                                 className = className.Substring (n + 1);
302                         // much faster than calling Activator.CreateInstance
303                         switch (className) {
304                                 case "FileCodeGroup":
305                                         return new FileCodeGroup (se, level);
306                                 case "FirstMatchCodeGroup":
307                                         return new FirstMatchCodeGroup (se, level);
308                                 case "NetCodeGroup":
309                                         return new NetCodeGroup (se, level);
310                                 case "UnionCodeGroup":
311                                         return new UnionCodeGroup (se, level);
312                                 default: // unknown
313                                         Type classType = Type.GetType (fullClassName);
314                                         CodeGroup cg = (CodeGroup) Activator.CreateInstance (classType, true);
315                                         cg.FromXml (se, level);
316                                         return cg;
317                         }
318                 }
319         }
320 }