2004-01-26 Sebastien Pouliot <spouliot@videotron.ca>
[mono.git] / mcs / class / corlib / System.Security.Policy / CodeGroup.cs
1 // System.Security.Policy.CodeGroup
2 //
3 // Author(s):
4 //   Nick Drochak (ndrochak@gol.com)
5 //
6 // (C) 2001 Nick Drochak, All rights reserved.
7
8 using System.Security.Policy;
9 using System.Security.Permissions;
10 using System.Collections;
11 using System;  // for MonoTODO attribute
12
13 namespace System.Security.Policy {
14
15         [Serializable]
16         public abstract class CodeGroup {
17                 PolicyStatement m_policy = null;
18                 IMembershipCondition m_membershipCondition = null;
19                 string m_description = null;
20                 string m_name = null;
21                 ArrayList m_children = new ArrayList();
22                 PolicyLevel m_level;
23
24                 public CodeGroup (IMembershipCondition membershipCondition, PolicyStatement policy)
25                 {
26                         if (null == membershipCondition)
27                                 throw new ArgumentNullException("Value cannot be null.");
28
29                         m_policy = policy;
30                         m_membershipCondition = membershipCondition;
31                 }
32
33                 // for PolicyLevel (to avoid validation duplication)
34                 internal CodeGroup (SecurityElement e) 
35                 {
36                         FromXml (e);
37                 }
38
39                 // abstract
40
41                 public abstract CodeGroup Copy();
42                 public abstract string MergeLogic {get;}
43                 public abstract PolicyStatement Resolve (Evidence evidence);
44                 public abstract CodeGroup ResolveMatchingCodeGroups(Evidence evidence);
45
46                 public PolicyStatement PolicyStatement {
47
48                         get { return m_policy; }
49
50                         set { m_policy = value; }
51                 }
52
53                 public string Description {
54
55                         get { return m_description; }
56
57                         set { m_description = value; }
58                 }
59
60                 public IMembershipCondition MembershipCondition  {
61
62                         get {
63                                 return m_membershipCondition;
64                         }
65
66                         set {
67                                 if (null == value)
68                                         throw new ArgumentException("Value cannot be null");
69                                 m_membershipCondition = value;
70                         }
71                 }
72
73                 public string Name {
74                         get { return m_name; }
75                         set { m_name = value; }
76                 }
77
78                 public IList Children {
79                         get { return m_children; }
80                         set {
81                                 if (null == value)
82                                         throw new ArgumentNullException ("value");
83                                 m_children = new ArrayList(value);
84                         }
85                 }
86
87                 public virtual string AttributeString {
88                         get {
89                                 if (null != m_policy)
90                                         return m_policy.AttributeString;
91                                 return null;
92                         }
93                 }
94
95                 public virtual string PermissionSetName {
96                         get {
97                                 if (m_policy.PermissionSet is Security.NamedPermissionSet)
98                                         return ((NamedPermissionSet)(m_policy.PermissionSet)).Name;
99                                 return null;
100                         }
101                 }
102
103                 public void AddChild(CodeGroup group)
104                 {
105                         if (null == group)
106                                 throw new ArgumentNullException("The group parameter cannot be null");
107                         m_children.Add(group);
108                 }
109
110                 public override bool Equals(object o)
111                 {
112                         if (!(o is CodeGroup))
113                                 return false;
114
115                         return Equals((CodeGroup)o, false);
116                 }
117
118                 public bool Equals(CodeGroup cg, bool compareChildren)
119                 {
120                         if (cg.Name != this.Name)
121                                 return false;
122
123                         if (cg.Description != this.Description)
124                                 return false;
125
126 //                      if (!cg.MembershipCondition.Equals ((IMembershipCondition)this.MembershipCondition))
127 //                              return false;
128
129                         if (compareChildren) {
130                                 int childCount = cg.Children.Count;
131                                 if (this.Children.Count != childCount)
132                                         return false;
133
134                                 for (int index = 0; index < childCount; index++) {
135                                         // LAMESPEC: are we supposed to check child equality recursively?
136                                         //              The docs imply 'no' but it seems natural to do a 'deep' compare.
137                                         //              Will check the children's children, and so-on unless we find out that
138                                         //              we shouldn't
139                                         if (!((CodeGroup)(this.Children[index])).Equals((CodeGroup)(cg.Children[index]), true))
140                                                 return false;
141                                 }
142                         }
143                         return true;
144                 }
145
146                 public void RemoveChild (CodeGroup group)
147                 {
148                         if (group != null)
149                                 m_children.Remove (group);
150                 }
151
152                 public override int GetHashCode ()
153                 {
154                         int hashCode = m_membershipCondition.GetHashCode ();
155                         if (m_policy != null)
156                                 hashCode += m_policy.GetHashCode ();
157                         return hashCode;
158                 }
159
160                 public void FromXml (SecurityElement e)
161                 {
162                         FromXml (e, null);
163                 }
164
165                 public void FromXml (SecurityElement e, PolicyLevel level)
166                 {
167                         if (null == e)
168                                 throw new ArgumentNullException("e");
169
170                         PermissionSet ps = null;
171                         SecurityElement pset = e.SearchForChildByTag ("PermissionSet");
172                         if (pset != null) {
173                                 ps = new NamedPermissionSet (pset);
174                         }
175                         else
176                                 ps = new NamedPermissionSet ("Nothing", new PermissionSet (PermissionState.None));
177                         m_policy = new PolicyStatement (ps);
178
179                         m_children.Clear ();
180                         if ((e.Children != null) && (e.Children.Count > 0)) {
181                                 foreach (SecurityElement se in e.Children) {
182                                         if (se.Tag == "CodeGroup") {
183                                                 this.AddChild (CodeGroup.CreateFromXml (se));
184                                         }
185                                 }
186                         }
187                         
188                         m_membershipCondition = null;
189                         SecurityElement mc = e.SearchForChildByTag ("IMembershipCondition");
190                         if (mc != null) {
191                                 string className = mc.Attribute ("class");
192                                 Type classType = Type.GetType (className);
193                                 if (classType == null)
194                                         classType = Type.GetType ("System.Security.Policy." + className);
195                                 m_membershipCondition = (IMembershipCondition) Activator.CreateInstance (classType);
196                                 m_membershipCondition.FromXml (mc, level);
197                         }
198
199                         m_name = e.Attribute("Name");
200                         m_description = e.Attribute("Description");
201
202                         // seems like we might need this to Resolve() in subclasses
203                         m_level = level;
204
205                         ParseXml (e, level);
206                 }
207
208                 protected virtual void ParseXml(SecurityElement e, PolicyLevel level)
209                 {
210                 }
211                 
212                 public SecurityElement ToXml()
213                 {
214                         return ToXml (null);
215                 }
216
217                 public SecurityElement ToXml (PolicyLevel level)
218                 {
219                         SecurityElement e = new SecurityElement("CodeGroup");
220                         e.AddAttribute("class", this.GetType().AssemblyQualifiedName);
221                         e.AddAttribute("version", "1");
222
223                         if (null != Name)
224                                 e.AddAttribute("Name", Name);
225
226                         if (null != Description)
227                                 e.AddAttribute("Description", Description);
228
229                         if (null != MembershipCondition)
230                                 e.AddChild(MembershipCondition.ToXml());
231
232                         if ((PolicyStatement != null) && (PolicyStatement.PermissionSet != null))
233                                 e.AddChild (PolicyStatement.PermissionSet.ToXml ());
234
235                         foreach (CodeGroup child in Children)
236                                 e.AddChild(child.ToXml());
237
238                         CreateXml(e, level);
239                         return e;
240                 }
241                 
242                 protected virtual void CreateXml(SecurityElement element, PolicyLevel level)
243                 {
244                 }
245
246                 // internal stuff
247
248                 internal static CodeGroup CreateFromXml (SecurityElement se) 
249                 {
250                         string fullClassName = se.Attribute ("class");
251                         string className = fullClassName;
252                         // many possible formats
253                         // a. "FirstMatchCodeGroup"
254                         // b. "System.Security.Policy.FirstMatchCodeGroup"
255                         // 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"
256                         int n = className.IndexOf (",");
257                         if (n > 0) {
258                                 className = className.Substring (0, n);
259                         }
260                         n = className.LastIndexOf (".");
261                         if (n > 0)
262                                 className = className.Substring (n + 1);
263                         // much faster than calling Activator.CreateInstance
264                         switch (className) {
265                                 case "FileCodeGroup":
266                                         return new FileCodeGroup (se);
267                                 case "FirstMatchCodeGroup":
268                                         return new FirstMatchCodeGroup (se);
269                                 case "NetCodeGroup":
270                                         return new NetCodeGroup (se);
271                                 case "UnionCodeGroup":
272                                         return new UnionCodeGroup (se);
273                                 default: // unknown
274                                         Type classType = Type.GetType (fullClassName);
275                                         return (CodeGroup) Activator.CreateInstance (classType, true);
276                         }
277                 }
278         }  // public abstract class CodeGroup
279 }  // namespace System.Security.Policy