2 * Copyright (C) 2003, 2004, 2005, 2006, 2007
3 * Robert Lougher <rob@lougher.org.uk>.
5 * This file is part of JamVM.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 static int isSameRuntimePackage(Class
*class1
, Class
*class2
) {
25 if(class1
!= class2
) {
26 ClassBlock
*cb1
= CLASS_CB(class1
);
27 ClassBlock
*cb2
= CLASS_CB(class2
);
29 /* The class loader must match */
30 if(cb1
->class_loader
!= cb2
->class_loader
)
33 /* And the package name */
35 /* If either class is an array compare the element
36 name to get rid of leading array characters (the
37 class loaders are the same) */
40 cb1
= CLASS_CB(cb1
->element_class
);
43 cb2
= CLASS_CB(cb2
->element_class
);
46 char *ptr1
= cb1
->name
;
47 char *ptr2
= cb2
->name
;
49 /* Names must match at least up to the last slash
50 in each. Note, we do not need to check for NULLs
51 because names _must_ be different (same loader,
52 but different class). */
54 while(*ptr1
++ == *ptr2
++);
56 for(ptr1
--; *ptr1
&& *ptr1
!= '/'; ptr1
++);
58 /* Didn't match to last slash in ptr1 */
62 for(ptr2
--; *ptr2
&& *ptr2
!= '/'; ptr2
++);
64 /* Didn't match to last slash in ptr2 */
73 int checkClassAccess(Class
*class1
, Class
*class2
) {
74 ClassBlock
*cb1
= CLASS_CB(class1
);
76 /* We can access it if it is public */
77 if(cb1
->access_flags
& ACC_PUBLIC
)
80 /* Or if they're members of the same runtime package */
81 return isSameRuntimePackage(class1
, class2
);
84 static int checkMethodOrFieldAccess(int access_flags
, Class
*decl_class
, Class
*class) {
86 /* Public methods and fields are always accessible */
87 if(access_flags
& ACC_PUBLIC
)
90 /* If the method or field is private, it must be declared in
91 the accessing class */
92 if(access_flags
& ACC_PRIVATE
)
93 return decl_class
== class;
95 /* The method or field must be protected or package-private */
97 /* If it is protected it is accessible if it is declared in the
98 accessing class or in a super-class */
99 if((access_flags
& ACC_PROTECTED
) && isSubClassOf(decl_class
, class))
102 /* Lastly protected and package-private methods/fields are accessible
103 if they are in the same runtime package as the accessing class */
104 return isSameRuntimePackage(decl_class
, class);
107 int checkMethodAccess(MethodBlock
*mb
, Class
*class) {
108 return checkMethodOrFieldAccess(mb
->access_flags
, mb
->class, class);
111 int checkFieldAccess(FieldBlock
*fb
, Class
*class) {
112 return checkMethodOrFieldAccess(fb
->access_flags
, fb
->class, class);