为了决定由传递给AccessController的checkPermission ()方法的Permission对象所代表的操作,是否包含在(或隐含在)和调用栈中的代码相关联的权限中,AccessController利用了一个名为implies ()的重要方法。这个implies ()方法是在Permission类以及PermissionCollection类和ProtectionDomain类中声明的。implies ()将一个Permission对象作为它惟一的参数,返回一 个布尔值true或false。Permission类的implies()方法确定由Permission对象所代表的权限,是否在本质上隐含在由一个不同的Permission对象所代表的权限中。PermissionColleclion和ProtectionDomain的implies ()方法确认了一个被传递的Permission是否包含或隐含在封装在 PermissionColiection 或 ProtectionDomain 中的Permission 对象集合中。
例如,读取/tmp目录下所有文件的权限本质上隐含了读取/tmp目录下特定文件/tmp/f的权限, 但是反过来则不成立。如果你询问一个代表了读取/tmp目录下的所有文件的权限的 FilePermission对象,它是否隐含了读取文件/tmp/f的权限,implies ()方法将返回true。但是如果你询问一个代表了读取/tmp/f权限的FilePermission对象是否隐含了读取/tmp下任何文件的权限时,implies ()方法将返回false。
implies ()方法被AccessController用来确定一个线程是否拥有进行某些操作的权限。例如, 如果AccessController的checkPerniission ()方法被调用,用以确定这个线程是否有权读取文件 /tmp/f,AccessController将调用和这个线程的调用栈中的每个栈帧相关联的ProtectionDomain对象的implies ()方法。对于每个implies ()方法,AccessController将把一个FilePermission对象 传递给它的checkPermission ()方法,这个FilePermission对象代表了读取文件/tmp/f的权限。每 个ProtectionDomain对象的implies ()方法会调用它封装的PermissionCoHection的implies ()方 法,传递给它同一个FilePermission。同样,每一个PermissionCollection会调用它包含的 Permission对象上的implies ()方法,再一次传递这个FilePermission对象的引用。一旦 PermissionCoIlection的implies ()方法遇到了一个Permission对象,这个Permission对象返回了 true,那么,这个PermissionCoIlection的implies ()方法也将返回true。只有当在 PermissionCollection中包含的所有Permission对象的implies ()方法都没有返回true时,这个 PermissionCoIlection才返回false。ProtectionDomain的implies ()方法简单地返回了 PermissionCollection的implies ()方法的返回值。如果AccessController从与一个特定栈帧相关联的ProtectionDomain的implies ()方法中得到true时,这个栈帧所代表的代码就拥有了执行这 个潜在不安全操作的权限。
第四个保护域名为BOOTSTRAP,它也是最后一个保护域,它不与policyfile.txt中的任何gram子句相对应,而是代表赋予所有由启动类装载器装载的代码的权限,启动类装载器负责装载Java API的class文件。在BOOTSTRAP保护域中的代码被赋予了java.lang.AnPermission,该权限允许做任何事。
为了使Example2a应用程序示范栈检查的过程,必须用一条合适的命令启动这个应用程序。当在Java 2 SDK版本1.2中使用这个应用程序时,这条命令采用以下形式:
java -Djava.security.manager -Djava.security.policy=policyfile.txt -Dcom.artina.ijva.cdrom.hone=d:ooks
InsideJVMmaauscriptcdron -cp .;jars/friend.jar;jars/stranger.jar Exanple2a
当AccessController执行它的栈检査时,它从栈顶栈帧10开始,逐个向下到栈帧1,找帧1是
由线程调用的第一个方法-类Example2a的main ()。在Example2a应用程序的例子中,调用栈的每一个栈帧都有权执行读取文件question.txt的操作。这是因为在调用栈上表示的四个保护域
-FRIEND、STRANGER、CD-ROM和BOOTSTRAP——都包含或隐含了读取当前目录下的
question.txt的FilePermission。当AccessController的checkPermission ()方法到达了栈底,而且 没有遇到任何栈帧无权读取这个文件的情况,它将正常返回,而不抛出任何异常。 FilelnputStream将继续执行并打开文件进行读取。Examp丨e2a应用程序读取question.txt的内容。