/// <summary>
        /// Determines whether the access request indicated by the
        /// specified permission should be allowed or denied, based on
        /// the current AccessControlContext and security policy.
        /// This method quietly returns if the access request
        /// is permitted, or throws an AccessControlException otherwise. The
        /// getPermission method of the AccessControlException returns the
        /// {@code perm} Permission object instance.
        /// </summary>
        /// <param name="perm"> the requested permission.
        /// </param>
        /// <exception cref="AccessControlException"> if the specified permission
        ///            is not permitted, based on the current security policy. </exception>
        /// <exception cref="NullPointerException"> if the specified permission
        ///            is {@code null} and is checked based on the
        ///            security policy currently in effect. </exception>

//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void checkPermission(Permission perm) throws AccessControlException
        public static void CheckPermission(Permission perm)
        {
            //System.err.println("checkPermission "+perm);
            //Thread.currentThread().dumpStack();

            if (perm == null)
            {
                throw new NullPointerException("permission can't be null");
            }

            AccessControlContext stack = StackAccessControlContext;

            // if context is null, we had privileged system code on the stack.
            if (stack == null)
            {
                Debug debug     = AccessControlContext.Debug;
                bool  dumpDebug = false;
                if (debug != null)
                {
                    dumpDebug = !Debug.isOn("codebase=");
//JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getCanonicalName method:
                    dumpDebug &= !Debug.isOn("permission=") || Debug.isOn("permission=" + perm.GetType().FullName);
                }

                if (dumpDebug && Debug.isOn("stack"))
                {
                    Thread.DumpStack();
                }

                if (dumpDebug && Debug.isOn("domain"))
                {
                    debug.println("domain (context is null)");
                }

                if (dumpDebug)
                {
                    debug.println("access allowed " + perm);
                }
                return;
            }

            AccessControlContext acc = stack.Optimize();

            acc.CheckPermission(perm);
        }
        /*
         * Check the domains associated with the limited privilege scope.
         */
        private void CheckPermission2(Permission perm)
        {
            if (!IsLimited)
            {
                return;
            }

            /*
             * Check the doPrivileged() context parameter, if present.
             */
            if (PrivilegedContext != null)
            {
                PrivilegedContext.CheckPermission2(perm);
            }

            /*
             * Ignore the limited permissions and parent fields of a wrapper
             * context since they were already carried down into the unwrapped
             * context.
             */
            if (IsWrapped)
            {
                return;
            }

            /*
             * Try to match any limited privilege scope.
             */
            if (Permissions != null)
            {
                Class permClass = perm.GetType();
                for (int i = 0; i < Permissions.Length; i++)
                {
                    Permission limit = Permissions[i];
                    if (limit.GetType().Equals(permClass) && limit.Implies(perm))
                    {
                        return;
                    }
                }
            }

            /*
             * Check the limited privilege scope up the call stack or the inherited
             * parent thread call stack of this ACC.
             */
            if (Parent != null)
            {
                /*
                 * As an optimization, if the parent context is the inherited call
                 * stack context from a parent thread then checking the protection
                 * domains of the parent context is redundant since they have
                 * already been merged into the child thread's context by
                 * optimize(). When parent is set to an inherited context this
                 * context was not directly created by a limited scope
                 * doPrivileged() and it does not have its own limited permissions.
                 */
                if (Permissions == null)
                {
                    Parent.CheckPermission2(perm);
                }
                else
                {
                    Parent.CheckPermission(perm);
                }
            }
        }