2009-06-30 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / class / corlib / System.Security.Policy / CodeGroup.cs
index 01830ef1d732db014a98b641948d341efaf4496e..2e8d833974d99f065461ab1411ae49015124b30d 100644 (file)
+//
 // System.Security.Policy.CodeGroup
 //
-// Author(s):
-//   Nick Drochak (ndrochak@gol.com)
+// Authors:
+//     Nick Drochak (ndrochak@gol.com)
+//     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // (C) 2001 Nick Drochak, All rights reserved.
+// Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
 
-using System.Security.Policy;
-using System.Security.Permissions;\r
 using System.Collections;
-using System;  // for MonoTODO attribute
+using System.Globalization;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security.Permissions;
+
+namespace System.Security.Policy {
 
-namespace System.Security.Policy
-{
        [Serializable]
-       public abstract class CodeGroup
-       {
-               PolicyStatement m_policy = null;
-               IMembershipCondition m_membershipCondition = null;
-               string m_description = null;
-               string m_name = null;
+#if NET_2_0
+       [ComVisible (true)]
+#endif
+       public abstract class CodeGroup {
+               PolicyStatement m_policy;
+               IMembershipCondition m_membershipCondition;
+               string m_description;
+               string m_name;
                ArrayList m_children = new ArrayList();
-               PolicyLevel m_level;
+//             PolicyLevel m_level;
 
-               public CodeGroup(IMembershipCondition membershipCondition,
-                                       PolicyStatement policy)
+#if NET_2_0
+               protected CodeGroup (IMembershipCondition membershipCondition, PolicyStatement policy)
+#else
+               public CodeGroup (IMembershipCondition membershipCondition, PolicyStatement policy)
+#endif
                {
                        if (null == membershipCondition)
-                               throw new ArgumentNullException("Value cannot be null.");
-                       m_policy = policy;
-                       m_membershipCondition = membershipCondition;
-               }
+                               throw new ArgumentNullException ("membershipCondition");
 
-               public abstract CodeGroup Copy();
-               public abstract string MergeLogic {get;}
-               public abstract PolicyStatement Resolve(        Evidence evidence);
-               public abstract CodeGroup ResolveMatchingCodeGroups(Evidence evidence);
+                       if (policy != null)
+                               m_policy = policy.Copy ();
+                       m_membershipCondition = membershipCondition.Copy ();
+               }
 
-               public PolicyStatement PolicyStatement
+               // for PolicyLevel (to avoid validation duplication)
+               internal CodeGroup (SecurityElement e, PolicyLevel level) 
                {
-                       get
-                       {
-                               return m_policy;
-                       }
-                       set
-                       {
-                               m_policy = value;
-                       }
+                       FromXml (e, level);
                }
 
-               public string Description
-               {
-                       get
-                       {
-                               return m_description;
-                       }
-                       set
-                       {
-                               m_description = value;
-                       }
+               // abstract
+
+               public abstract CodeGroup Copy ();
+
+               public abstract string MergeLogic { get; }
+
+               public abstract PolicyStatement Resolve (Evidence evidence);
+
+               public abstract CodeGroup ResolveMatchingCodeGroups (Evidence evidence);
+
+               // properties
+
+               public PolicyStatement PolicyStatement {
+                       get { return m_policy; }
+                       set { m_policy = value; }
                }
 
-               public IMembershipCondition MembershipCondition 
-               {
-                       get
-                       {
-                               return m_membershipCondition;
-                       }
-                       set
-                       {
+               public string Description {
+                       get { return m_description; }
+                       set { m_description = value; }
+               }
+
+               public IMembershipCondition MembershipCondition  {
+                       get { return m_membershipCondition; }
+                       set {
                                if (null == value)
-                                       throw new ArgumentException("Value cannot be null");
+                                       throw new ArgumentException ("value");
                                m_membershipCondition = value;
                        }
                }
 
-               public string Name 
-               {
-                       get
-                       {
-                               return m_name;
-                       }
-                       set
-                       {
-                               m_name = value;
-                       }
+               public string Name {
+                       get { return m_name; }
+                       set { m_name = value; }
                }
 
-               public IList Children
-               {
-                       get
-                       {
-                               return m_children;
-                       }
-                       set
-                       {
+               public IList Children {
+                       get { return m_children; }
+                       set {
                                if (null == value)
-                                       throw new ArgumentException("Value cannot be null");
-                               m_children = new ArrayList(value);
+                                       throw new ArgumentNullException ("value");
+                               m_children = new ArrayList (value);
                        }
                }
 
-               public virtual string AttributeString
-               {
-                       get
-                       {
+               public virtual string AttributeString {
+                       get {
                                if (null != m_policy)
                                        return m_policy.AttributeString;
-
                                return null;
                        }
                }
 
-               public virtual string PermissionSetName
-               {
-                       get
-                       {
+               public virtual string PermissionSetName {
+                       get {
+                               if (m_policy == null)
+                                       return null;
                                if (m_policy.PermissionSet is Security.NamedPermissionSet)
                                        return ((NamedPermissionSet)(m_policy.PermissionSet)).Name;
-
                                return null;
                        }
                }
 
-               public void AddChild(CodeGroup group)
+               public void AddChild (CodeGroup group)
                {
                        if (null == group)
-                               throw new ArgumentNullException("The group parameter cannot be null");
-                       m_children.Add(group);
+                               throw new ArgumentNullException ("group");
+
+                       m_children.Add (group.Copy ());
                }
 
-               public override bool Equals(object o)
+               public override bool Equals (object o)
                {
-                       if (!(o is CodeGroup))
+                       CodeGroup cg = (o as CodeGroup);
+                       if (cg == null)
                                return false;
 
-                       return Equals((CodeGroup)o, false);
+                       return Equals (cg, false);
                }
 
-               public bool Equals(CodeGroup cg, bool compareChildren)
+               public bool Equals (CodeGroup cg, bool compareChildren)
                {
                        if (cg.Name != this.Name)
                                return false;
@@ -145,89 +156,121 @@ namespace System.Security.Policy
                        if (cg.Description != this.Description)
                                return false;
 
-                       if (cg.MembershipCondition != this.MembershipCondition)
+                       if (!cg.MembershipCondition.Equals (m_membershipCondition))
                                return false;
 
-                       if (compareChildren)
-                       {
+                       if (compareChildren) {
                                int childCount = cg.Children.Count;
                                if (this.Children.Count != childCount)
                                        return false;
 
-                               for (int index = 0; index < childCount; index++)
-                               {
-                                       // LAMESPEC: are we supposed to check child equality recursively?
-                                       //              The docs imply 'no' but it seems natural to do a 'deep' compare.
-                                       //              Will check the children's children, and so-on unless we find out that
-                                       //              we shouldn't
-                                       if (!((CodeGroup)(this.Children[index])).Equals((CodeGroup)(cg.Children[index]), true))
+                               for (int index = 0; index < childCount; index++) {
+                                       // not a deep compare
+                                       if (!((CodeGroup)(this.Children [index])).Equals ((CodeGroup)(cg.Children [index]), false))
                                                return false;
                                }
                        }
-
                        return true;
-
                }
 
-               public void RemoveChild(CodeGroup group)
+               public void RemoveChild (CodeGroup group)
                {
-                       if (!m_children.Contains(group))
-                               throw new ArgumentException();
-
-                       m_children.Remove(group);
+                       if (group != null)
+                               m_children.Remove (group);
                }
 
-               [MonoTODO]
-               public override int GetHashCode()
+               public override int GetHashCode ()
                {
-                       return 42;
+                       int hashCode = m_membershipCondition.GetHashCode ();
+                       if (m_policy != null)
+                               hashCode += m_policy.GetHashCode ();
+                       return hashCode;
                }
 
-               public void FromXml(SecurityElement e)
+               public void FromXml (SecurityElement e)
                {
-                       FromXml(e, (PolicyLevel)null);
+                       FromXml (e, null);
                }
 
-               [MonoTODO]
-               public void FromXml(SecurityElement e, PolicyLevel level        )
+               public void FromXml (SecurityElement e, PolicyLevel level)
                {
                        if (null == e)
                                throw new ArgumentNullException("e");
 
-                       // Not sure what might be serialized in this XML, so just do the strings for now
-                       // and null's for everything else
-                       m_children = null;
-                       m_policy = null;
+                       PermissionSet ps = null;
+                       string psetname = e.Attribute ("PermissionSetName");
+                       if ((psetname != null) && (level != null)) {
+                               ps = level.GetNamedPermissionSet (psetname);
+                       }
+                       else {
+                               SecurityElement pset = e.SearchForChildByTag ("PermissionSet");
+                               if (pset != null) {
+                                       Type classType = Type.GetType (pset.Attribute ("class"));
+                                       ps = (PermissionSet) Activator.CreateInstance (classType, true);
+                                       ps.FromXml (pset);
+                               }
+                               else {
+                                       ps = new PermissionSet (new PermissionSet (PermissionState.None));
+                               }
+                       }
+                       m_policy = new PolicyStatement (ps);
+
+                       m_children.Clear ();
+                       if ((e.Children != null) && (e.Children.Count > 0)) {
+                               foreach (SecurityElement se in e.Children) {
+                                       if (se.Tag == "CodeGroup") {
+                                               this.AddChild (CodeGroup.CreateFromXml (se, level));
+                                       }
+                               }
+                       }
+                       
                        m_membershipCondition = null;
+                       SecurityElement mc = e.SearchForChildByTag ("IMembershipCondition");
+                       if (mc != null) {
+                               string className = mc.Attribute ("class");
+                               Type classType = Type.GetType (className);
+                               if (classType == null)
+                                       classType = Type.GetType ("System.Security.Policy." + className);
+                               m_membershipCondition = (IMembershipCondition) Activator.CreateInstance (classType, true);
+                               m_membershipCondition.FromXml (mc, level);
+                       }
 
                        m_name = e.Attribute("Name");
                        m_description = e.Attribute("Description");
 
                        // seems like we might need this to Resolve() in subclasses
-                       m_level = level;
+                       //m_level = level;
 
-                       ParseXml(e, level);
+                       ParseXml (e, level);
                }
 
-               protected virtual void ParseXml(SecurityElement e, PolicyLevel level)
+               protected virtual void ParseXml (SecurityElement e, PolicyLevel level)
                {
                }
                
-               public SecurityElement ToXml()
+               public SecurityElement ToXml ()
                {
-                       return ToXml(null);
+                       return ToXml (null);
                }
 
-               [MonoTODO("Not sure what to do with PolicyLevel parameter")]
-                public SecurityElement ToXml(PolicyLevel level)\r
+               public SecurityElement ToXml (PolicyLevel level)
                {
                        SecurityElement e = new SecurityElement("CodeGroup");
                        e.AddAttribute("class", this.GetType().AssemblyQualifiedName);
                        e.AddAttribute("version", "1");
-                       e.AddAttribute("Name", Name);
-                       e.AddAttribute("Description", Description);
-                       e.AddChild(MembershipCondition.ToXml());
-                       e.AddChild(PolicyStatement.PermissionSet.ToXml());
+
+                       if (null != Name)
+                               e.AddAttribute("Name", Name);
+
+                       if (null != Description)
+                               e.AddAttribute("Description", Description);
+
+                       if (null != MembershipCondition)
+                               e.AddChild(MembershipCondition.ToXml());
+
+                       if ((PolicyStatement != null) && (PolicyStatement.PermissionSet != null))
+                               e.AddChild (PolicyStatement.PermissionSet.ToXml ());
+
                        foreach (CodeGroup child in Children)
                                e.AddChild(child.ToXml());
 
@@ -235,9 +278,43 @@ namespace System.Security.Policy
                        return e;
                }
                
-               protected virtual void CreateXml(SecurityElement element, PolicyLevel level)
+               protected virtual void CreateXml (SecurityElement element, PolicyLevel level)
                {
                }
-       }  // public abstract class CodeGroup
 
-}  // namespace System.Security.Policy
\ No newline at end of file
+               // internal stuff
+
+               internal static CodeGroup CreateFromXml (SecurityElement se, PolicyLevel level) 
+               {
+                       string fullClassName = se.Attribute ("class");
+                       string className = fullClassName;
+                       // many possible formats
+                       // a. "FirstMatchCodeGroup"
+                       // b. "System.Security.Policy.FirstMatchCodeGroup"
+                       // 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"
+                       int n = className.IndexOf (",");
+                       if (n > 0) {
+                               className = className.Substring (0, n);
+                       }
+                       n = className.LastIndexOf (".");
+                       if (n > 0)
+                               className = className.Substring (n + 1);
+                       // much faster than calling Activator.CreateInstance
+                       switch (className) {
+                               case "FileCodeGroup":
+                                       return new FileCodeGroup (se, level);
+                               case "FirstMatchCodeGroup":
+                                       return new FirstMatchCodeGroup (se, level);
+                               case "NetCodeGroup":
+                                       return new NetCodeGroup (se, level);
+                               case "UnionCodeGroup":
+                                       return new UnionCodeGroup (se, level);
+                               default: // unknown
+                                       Type classType = Type.GetType (fullClassName);
+                                       CodeGroup cg = (CodeGroup) Activator.CreateInstance (classType, true);
+                                       cg.FromXml (se, level);
+                                       return cg;
+                       }
+               }
+       }
+}