/* * Copyright 2009-2010 MBTE Sweden AB. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.mbte.groovypp.compiler; import org.codehaus.groovy.ast.ClassNode; import org.objectweb.asm.Opcodes; public class AccessibilityCheck { public static boolean isAccessible(int modifiers, ClassNode declaringClass, ClassNode placeClass, ClassNode accessType) { if (accessType != null && !isAccessible(accessType.getModifiers(), accessType.getOuterClass(), placeClass, null)) return false; if (declaringClass == null) return true; if ((modifiers & Opcodes.ACC_PRIVATE) != 0) { return getToplevelClass(declaringClass).equals(getToplevelClass(placeClass)); } else if ((modifiers & Opcodes.ACC_PROTECTED) != 0) { if (samePackage(declaringClass, placeClass)) return true; while (placeClass != null) { if (placeClass.isDerivedFrom(declaringClass)) { return accessType == null || accessType.isDerivedFrom(placeClass); } if ((placeClass.getModifiers() & Opcodes.ACC_STATIC) != 0) break; placeClass = placeClass.getOuterClass(); } return false; } else if ((modifiers & Opcodes.ACC_PUBLIC) != 0) { return true; } // package local if (!samePackage(declaringClass, placeClass)) return false; // check the entire inheritance chain. ClassNode clazz = null; if (accessType != null) { clazz = accessType; } else { while (placeClass != null) { if (placeClass.isDerivedFrom(declaringClass)) { clazz = placeClass; break; } if ((placeClass.getModifiers() & Opcodes.ACC_STATIC) != 0) break; placeClass = placeClass.getOuterClass(); } } while (clazz != null && !clazz.equals(declaringClass)) { if (!samePackage(declaringClass, clazz)) return false; clazz = clazz.getSuperClass(); } return true; } private static ClassNode getToplevelClass(ClassNode node) { ClassNode toplevel = node; while (toplevel.getOuterClass() != null) toplevel = toplevel.getOuterClass(); return toplevel; } private static boolean samePackage(ClassNode c1, ClassNode c2) { if (c1.redirect().equals(c2.redirect())) return true; String name1 = c1.getPackageName(); String name2 = c2.getPackageName(); if (name1 == null) name1 = ""; // why is it nullable? if (name2 == null) name2 = ""; return name1.equals(name2); } }