org.mbte.groovypp.compiler.AccessibilityCheck.java Source code

Java tutorial

Introduction

Here is the source code for org.mbte.groovypp.compiler.AccessibilityCheck.java

Source

/*
 * Copyright 2009-2011 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);
    }
}