Example usage for org.objectweb.asm Opcodes ACC_PROTECTED

List of usage examples for org.objectweb.asm Opcodes ACC_PROTECTED

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes ACC_PROTECTED.

Prototype

int ACC_PROTECTED

To view the source code for org.objectweb.asm Opcodes ACC_PROTECTED.

Click Source Link

Usage

From source file:org.mbte.groovypp.compiler.AccessibilityCheck.java

License:Apache License

public static boolean isAccessible(int modifiers, ClassNode declaringClass, ClassNode placeClass,
        ClassNode accessType) {/*from w w  w . jav a  2s.c  o m*/
    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;
}

From source file:org.mbte.groovypp.compiler.TraitASTTransform.java

License:Apache License

public void visit(ASTNode[] nodes, final SourceUnit source) {
    ModuleNode module = (ModuleNode) nodes[0];
    List<ClassNode> toProcess = new LinkedList<ClassNode>();
    final boolean forceTyped = source.getName().endsWith(".gpp");
    AnnotationNode pkgTypedAnn = getTypedAnnotation(module.getPackage());
    for (ClassNode classNode : module.getClasses()) {
        boolean process = false;
        boolean typed = false;
        for (AnnotationNode ann : classNode.getAnnotations()) {
            final String withoutPackage = ann.getClassNode().getNameWithoutPackage();
            if (withoutPackage.equals("Trait")) {
                process = true;/*from   w ww . jav a 2  s. c  o m*/
            }
            if (withoutPackage.equals("Typed")) {
                typed = true;
                ann.getClassNode().setRedirect(TypeUtil.TYPED);
            }
        }

        if (forceTyped && !typed) {
            typed = true;
            classNode.addAnnotation(pkgTypedAnn != null ? pkgTypedAnn : new AnnotationNode(TypeUtil.TYPED));
        }

        if (process) {
            toProcess.add(classNode);
            if (!typed) {
                classNode.addAnnotation(pkgTypedAnn != null ? pkgTypedAnn : new AnnotationNode(TypeUtil.TYPED));
            }
        }
    }

    for (ClassNode classNode : toProcess) {
        if (classNode.isInterface() || classNode.isEnum() || classNode.isAnnotationDefinition()) {
            source.addError(new SyntaxException("@Trait can be applied only to <class>",
                    classNode.getLineNumber(), classNode.getColumnNumber()));
            continue;
        }

        if (classNode.getDeclaredConstructors().size() > 0) {
            ConstructorNode constructor = classNode.getDeclaredConstructors().get(0);
            source.addError(new SyntaxException("Constructors are not allowed in traits",
                    constructor.getLineNumber(), constructor.getColumnNumber()));
            continue;
        }

        if (classNode.getObjectInitializerStatements().size() > 0) {
            Statement initializer = classNode.getObjectInitializerStatements().get(0);
            source.addError(new SyntaxException("Object initializers are not allowed in traits",
                    initializer.getLineNumber(), initializer.getColumnNumber()));
            continue;
        }

        int mod = classNode.getModifiers();
        mod &= ~Opcodes.ACC_FINAL;
        mod |= Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE;
        classNode.setModifiers(mod);

        String name = classNode.getNameWithoutPackage() + "$TraitImpl";
        String fullName = ASTHelper.dot(classNode.getPackageName(), name);

        InnerClassNode innerClassNode = new InnerClassNode(classNode, fullName,
                ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT, ClassHelper.OBJECT_TYPE, new ClassNode[] { classNode },
                null);
        AnnotationNode typedAnn = new AnnotationNode(TypeUtil.TYPED);
        final Expression member = getTypedAnnotation(classNode).getMember("debug");
        if (member != null && member instanceof ConstantExpression
                && ((ConstantExpression) member).getValue().equals(Boolean.TRUE))
            typedAnn.addMember("debug", ConstantExpression.TRUE);
        innerClassNode.addAnnotation(typedAnn);

        innerClassNode.setGenericsTypes(classNode.getGenericsTypes());

        ClassNode superClass = classNode.getSuperClass();
        if (!ClassHelper.OBJECT_TYPE.equals(superClass)) {
            ClassNode[] ifaces = classNode.getInterfaces();
            ClassNode[] newIfaces = new ClassNode[ifaces.length + 1];
            newIfaces[0] = superClass;
            System.arraycopy(ifaces, 0, newIfaces, 1, ifaces.length);
            classNode.setSuperClass(ClassHelper.OBJECT_TYPE);
            classNode.setInterfaces(newIfaces);
        }

        classNode.getModule().addClass(innerClassNode);

        innerClassNode.addMethod("getMetaClass", ACC_PUBLIC | ACC_ABSTRACT, ClassHelper.METACLASS_TYPE,
                Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
        innerClassNode.addMethod("setMetaClass", ACC_PUBLIC | ACC_ABSTRACT, ClassHelper.VOID_TYPE,
                new Parameter[] { new Parameter(ClassHelper.METACLASS_TYPE, "value") }, ClassNode.EMPTY_ARRAY,
                null);
        innerClassNode.addMethod("getProperty", ACC_PUBLIC | ACC_ABSTRACT, ClassHelper.OBJECT_TYPE,
                new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name") }, ClassNode.EMPTY_ARRAY,
                null);
        innerClassNode.addMethod("setProperty", ACC_PUBLIC | ACC_ABSTRACT, ClassHelper.VOID_TYPE,
                new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name"),
                        new Parameter(ClassHelper.OBJECT_TYPE, "value") },
                ClassNode.EMPTY_ARRAY, null);
        innerClassNode.addMethod("invokeMethod", ACC_PUBLIC | ACC_ABSTRACT, ClassHelper.OBJECT_TYPE,
                new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name"),
                        new Parameter(ClassHelper.OBJECT_TYPE, "args") },
                ClassNode.EMPTY_ARRAY, null);

        for (FieldNode fieldNode : classNode.getFields()) {
            //                if (fieldNode.isStatic())
            //                    continue;

            final String getterName = "get" + Verifier.capitalize(fieldNode.getName());
            MethodNode getter = classNode.getGetterMethod(getterName);
            if (getter == null) {
                getter = classNode.addMethod(getterName, ACC_PUBLIC | ACC_ABSTRACT, fieldNode.getType(),
                        Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
                addFieldAnnotation(innerClassNode, fieldNode, getter);
            }

            // We need the second getter (and setter) to compile non-synthetic first one referring to the field.
            // The references inside the first one will be retargeted to the second one.
            final MethodNode realGetter = classNode.addMethod("get$" + fieldNode.getName(),
                    ACC_PUBLIC | ACC_ABSTRACT, fieldNode.getType(), Parameter.EMPTY_ARRAY,
                    ClassNode.EMPTY_ARRAY, null);
            addFieldAnnotation(innerClassNode, fieldNode, realGetter);

            final String setterName = "set" + Verifier.capitalize(fieldNode.getName());
            Parameter valueParam = new Parameter(fieldNode.getType(), "$value");
            MethodNode setter = classNode.getSetterMethod(setterName);
            if (setter == null) {
                setter = classNode.addMethod(setterName, ACC_PUBLIC | ACC_ABSTRACT, ClassHelper.VOID_TYPE,
                        new Parameter[] { valueParam }, ClassNode.EMPTY_ARRAY, null);
                addFieldAnnotation(innerClassNode, fieldNode, setter);
            }

            final MethodNode realSetter = classNode.addMethod("set$" + fieldNode.getName(),
                    ACC_PUBLIC | ACC_ABSTRACT, ClassHelper.VOID_TYPE, new Parameter[] { valueParam },
                    ClassNode.EMPTY_ARRAY, null);
            addFieldAnnotation(innerClassNode, fieldNode, realSetter);

            if (fieldNode.hasInitialExpression()) {
                final Expression initial = fieldNode.getInitialValueExpression();
                fieldNode.setInitialValueExpression(null);

                final MethodNode initMethod = innerClassNode.addMethod("__init_" + fieldNode.getName(),
                        ACC_PUBLIC | ACC_STATIC, ClassHelper.VOID_TYPE,
                        new Parameter[] { new Parameter(classNode, "$self") }, ClassNode.EMPTY_ARRAY,
                        new BlockStatement());

                final PropertyExpression prop = new PropertyExpression(new VariableExpression("$self"),
                        fieldNode.getName());
                prop.setSourcePosition(fieldNode);
                final CastExpression cast = new CastExpression(fieldNode.getType(), initial);
                cast.setSourcePosition(initial);
                final BinaryExpression assign = new BinaryExpression(prop,
                        Token.newSymbol(Types.ASSIGN, -1, -1), cast);
                assign.setSourcePosition(initial);
                final ExpressionStatement assignExpr = new ExpressionStatement(assign);
                assignExpr.setSourcePosition(initial);
                ((BlockStatement) initMethod.getCode()).addStatement(assignExpr);
            }

            innerClassNode.addField(fieldNode);
        }

        classNode.getFields().clear();
        classNode.getProperties().clear();

        for (MethodNode methodNode : classNode.getMethods()) {
            if (methodNode.getCode() == null)
                continue;

            if (methodNode.isStatic()) {
                source.addError(new SyntaxException("Static methods are not allowed in traits",
                        methodNode.getLineNumber(), methodNode.getColumnNumber()));
            }

            if (!methodNode.isPublic()) {
                source.addError(new SyntaxException("Non-public methods are not allowed in traits",
                        methodNode.getLineNumber(), methodNode.getColumnNumber()));
            }

            mod = methodNode.getModifiers();
            mod &= ~(Opcodes.ACC_FINAL | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
            mod |= Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC;
            methodNode.setModifiers(mod);

            Parameter[] parameters = methodNode.getParameters();

            Parameter[] newParameters = new Parameter[parameters.length + 1];
            final Parameter self = new Parameter(classNode, "$self");
            newParameters[0] = self;
            System.arraycopy(parameters, 0, newParameters, 1, parameters.length);

            MethodNode newMethod = innerClassNode.addMethod(methodNode.getName(), ACC_PUBLIC,
                    methodNode.getReturnType(), newParameters, ClassNode.EMPTY_ARRAY, methodNode.getCode());
            ArrayList<GenericsType> gt = new ArrayList<GenericsType>();
            if (classNode.getGenericsTypes() != null)
                for (int i = 0; i < classNode.getGenericsTypes().length; i++) {
                    GenericsType genericsType = classNode.getGenericsTypes()[i];
                    gt.add(genericsType);
                }
            if (methodNode.getGenericsTypes() != null)
                for (int i = 0; i < methodNode.getGenericsTypes().length; i++) {
                    GenericsType genericsType = methodNode.getGenericsTypes()[i];
                    gt.add(genericsType);
                }

            if (!gt.isEmpty())
                newMethod.setGenericsTypes(gt.toArray(new GenericsType[gt.size()]));

            AnnotationNode annotationNode = new AnnotationNode(TypeUtil.HAS_DEFAULT_IMPLEMENTATION);
            annotationNode.addMember("value", new ClassExpression(innerClassNode));
            methodNode.addAnnotation(annotationNode);

            methodNode.setCode(null);
        }
    }
}

From source file:org.mule.tools.maven.plugin.module.analyze.asm.AccessUtils.java

License:Open Source License

public static boolean isProtected(int access) {
    return (access & Opcodes.ACC_PROTECTED) == Opcodes.ACC_PROTECTED;
}

From source file:org.openspotlight.bundle.language.java.resolver.JavaGraphNodeSupport.java

License:Open Source License

/**
 * Adds the type on current context. This method should be used on current classpath elements only. The types declared outside
 * this classpath should be added with method {@link #addTypeOnAbstractContext(Class, String, String)}.
 * /*from  w  w  w . j  a  v  a  2  s. com*/
 * @param nodeType the node type
 * @param packageName the package name
 * @param nodeName the node name
 * @param access the access
 * @param parentType the parent type, if null will use package as parent
 * @return the t
 * @throws Exception the exception
 */
@SuppressWarnings("unchecked")
public <T extends JavaType> T addTypeOnCurrentContext(final Class<T> nodeType, final String packageName,
        final String nodeName, final int access, final Node parentType) throws Exception {
    if (logger.isDebugEnabled()) {
        logger.debug(" adding type on current context " + packageName + "_" + nodeName + " with parent "
                + (parentType != null ? parentType.getName() : "null"));
    }

    if (usingCache && nodesFromThisContext.containsKey(packageName + nodeName)) {
        return (T) nodesFromThisContext.get(packageName + nodeName);
    }
    if (JavaTypePrimitive.class.equals(nodeType)) {
        final T newType = abstractContextRootNode.addChildNode(nodeType, nodeName);
        newType.setSimpleName(nodeName);
        newType.setQualifiedName(nodeName);
        return newType;
    }
    final JavaPackage newPackage = currentContextRootNode.addChildNode(JavaPackage.class, packageName);
    T newType = null;

    if (parentType != null) {
        newType = parentType.addChildNode(nodeType, nodeName);
    } else {
        newType = newPackage.addChildNode(nodeType, nodeName);
    }

    newType.setSimpleName(nodeName);
    newType.setQualifiedName(Strings.tryToRemoveBegginingFrom(JavaConstants.DEFAULT_PACKAGE + ".",
            packageName + "." + nodeName.replaceAll("[$]", ".")));
    session.addLink(PackageType.class, newPackage, newType, false);
    final boolean isPublic = (access & Opcodes.ACC_PUBLIC) != 0;
    final boolean isPrivate = (access & Opcodes.ACC_PRIVATE) != 0;
    final boolean isStatic = (access & Opcodes.ACC_STATIC) != 0;
    final boolean isFinal = (access & Opcodes.ACC_FINAL) != 0;
    final boolean isProtected = (access & Opcodes.ACC_PROTECTED) != 0;
    newType.setPublic(isPublic);
    newType.setPrivate(isPrivate);
    newType.setStatic(isStatic);
    newType.setFinal(isFinal);
    newType.setProtected(isProtected);

    final JavaPackage newAbstractPackage = abstractContextRootNode.addChildNode(JavaPackage.class, packageName);
    final JavaType newAbstractType = newAbstractPackage.addChildNode(JavaType.class, nodeName);
    newAbstractType.setQualifiedName(Strings.tryToRemoveBegginingFrom(JavaConstants.DEFAULT_PACKAGE + ".",
            packageName + "." + nodeName.replaceAll("[$]", ".")));
    newAbstractType.setSimpleName(nodeName);

    session.addLink(PackageType.class, newPackage, newType, false);
    session.addLink(AbstractTypeBind.class, newAbstractType, newType, false);
    nodesFromThisContext.put(packageName + nodeName, newType);
    if (logger.isInfoEnabled()) {
        logger.info("added class " + nodeType.getSimpleName() + " " + packageName + "." + nodeName);
    }
    return newType;
}

From source file:org.openspotlight.bundle.language.java.resolver.JavaGraphNodeSupport.java

License:Open Source License

/**
 * Insert field data./*w w  w . j  av  a2 s.  c  o m*/
 * 
 * @param field the field
 * @param fieldType the field type
 * @param access the access
 * @param isArray the is array
 * @param dimension the dimension
 * @throws Exception the exception
 */
private void insertFieldData(final JavaDataField field, final JavaType fieldType, final int access,
        final boolean isArray, final int dimension) throws Exception {
    final DataType fieldTypeLink = session.addLink(DataType.class, field, fieldType, false);
    fieldTypeLink.setArray(isArray);
    fieldTypeLink.setArrayDimension(dimension);
    final boolean isFieldPublic = (access & Opcodes.ACC_PUBLIC) != 0;
    final boolean isFieldPrivate = (access & Opcodes.ACC_PRIVATE) != 0;
    final boolean isFieldStatic = (access & Opcodes.ACC_STATIC) != 0;
    final boolean isFieldFinal = (access & Opcodes.ACC_FINAL) != 0;
    final boolean isFieldProtected = (access & Opcodes.ACC_PROTECTED) != 0;
    final boolean isFieldTransient = (access & Opcodes.ACC_TRANSIENT) != 0;
    final boolean isFieldVolatile = (access & Opcodes.ACC_VOLATILE) != 0;
    field.setPublic(isFieldPublic);
    field.setPrivate(isFieldPrivate);
    field.setStatic(isFieldStatic);
    field.setFinal(isFieldFinal);
    field.setProtected(isFieldProtected);
    field.setTransient(isFieldTransient);
    field.setVolatile(isFieldVolatile);
}

From source file:org.openspotlight.bundle.language.java.resolver.JavaGraphNodeSupport.java

License:Open Source License

/**
 * Sets the method data.// ww w.ja v a 2s. c o m
 * 
 * @param method the method
 * @param access the access
 */
private void setMethodData(final JavaMethod method, final int access) {
    final boolean isMethodPublic = (access & Opcodes.ACC_PUBLIC) != 0;
    final boolean isMethodPrivate = (access & Opcodes.ACC_PRIVATE) != 0;
    final boolean isMethodStatic = (access & Opcodes.ACC_STATIC) != 0;
    final boolean isMethodFinal = (access & Opcodes.ACC_FINAL) != 0;
    final boolean isMethodProtected = (access & Opcodes.ACC_PROTECTED) != 0;
    final boolean isMethodSynchronized = (access & Opcodes.ACC_SYNCHRONIZED) != 0;
    method.setPublic(isMethodPublic);
    method.setPrivate(isMethodPrivate);
    method.setStatic(isMethodStatic);
    method.setFinal(isMethodFinal);
    method.setProtected(isMethodProtected);
    method.setSynchronized(isMethodSynchronized);
}

From source file:org.osjava.jardiff.Tools.java

License:Apache License

private static boolean isAccessIncompatible(int oldAccess, int newAccess) {
    if (has(newAccess, Opcodes.ACC_PUBLIC)) {
        return false;
    } else if (has(newAccess, Opcodes.ACC_PROTECTED)) {
        return has(oldAccess, Opcodes.ACC_PUBLIC);
    } else if (has(newAccess, Opcodes.ACC_PRIVATE)) {
        return not(oldAccess, Opcodes.ACC_PRIVATE);
    } else {/*from   ww  w  .  j a  va  2s . c om*/
        // new access is package, it is incompatible if old access was public or protected
        return has(oldAccess, Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED);
    }
}

From source file:org.osjava.jardiff.Tools.java

License:Apache License

/**
 * Returns whether a field's newAccess is incompatible with oldAccess
 * following <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html">Java Language Specification, Java SE 7 Edition</a>:
 * <ul>//from   www.  java 2s.  co m
 *   <li><a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.9">13.4.7 Access to Members and Constructors</a><ul>
 *     <li>Changing the declared access of a member or constructor to permit less access
 *        <b>may break compatibility</b> with pre-existing binaries, causing a linkage error to be thrown when these binaries are resolved.
 *     </li>
 *     <li>The binary format is defined so that changing a member or constructor to be more accessible does not cause a
 *         linkage error when a subclass (already) defines a method to have less access.
 *     </li>
 *     </ul></li>
 *   <li><a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.9">13.4.9 final Fields and Constants</a><ul>
 *     <li>If a field that was not declared final is changed to be declared final,
 *         then it <b>can break compatibility</b> with pre-existing binaries that attempt to assign new values to the field.</li>
 *     <li>Deleting the keyword final or changing the value to which a <i>non-final</i> field is initialized
 *         <b>does not break compatibility</b> with existing binaries.</li>
 *     <li>If a field is a constant variable (4.12.4),
 *         then deleting the keyword final or changing its value
 *         will <i>not break compatibility</i> with pre-existing binaries by causing them not to run,
 *         but they will not see any new value for the usage of the field unless they are recompiled.
 *         This is true even if the usage itself is not a compile-time constant expression (15.28).
 *         Such changes <b>break functional backward compatibility</b>!</li>
 *     </ul></li>
 *   <li><a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.10">13.4.10 static Fields</a><ul>
 *     <li>If a field that is not declared private was not declared static
 *         and is changed to be declared static, or vice versa,
 *         then a linkage error, specifically an IncompatibleClassChangeError,
 *         will result if the field is used by a pre-existing binary which expected a field of the other kind.
 *         Such changes <b>break backward compatibility</b>!</li>
 *     </ul></li>
 *   <li><a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.11">13.4.11. transient Fields </a><ul>
 *     <li>Adding or deleting a transient modifier of a field
 *         <b>does not break compatibility</b> with pre-existing binaries.</li>
 *   </ul></li>
 *   <li><a href="http://www.wsu.edu/UNIX_Systems/java/langspec-1.0/13.doc.html#45194">13.4.11 volatile Fields (JLS 1.0)</a><ul>
 *     <li>If a field that is not declared private was not declared volatile
 *         and is changed to be declared volatile, or vice versa, then a linkage time error,
 *         specifically an IncompatibleClassChangeError, may result if the field is used
 *         by a preexisting binary that expected a field of the opposite volatility.
 *         Such changes <b>break backward compatibility</b>!</li>
 *   </ul></li>
 * </ul>
 *
 * @param oldAccess
 * @param newAccess
 * @return
 */
public static boolean isFieldAccessChange(final int oldAccess, final int newAccess) {
    if (isAccessIncompatible(oldAccess, newAccess)) {
        return true; // 13.4.7
    }
    if (not(oldAccess, Opcodes.ACC_FINAL) && has(newAccess, Opcodes.ACC_FINAL)) {
        return true; // 13.4.9 #1
    } else {
        final int compatibleChanges = Opcodes.ACC_FINAL | // 13.4.9 #2
                Opcodes.ACC_TRANSIENT; // 13.4.11 #1
        final int accessPermissions = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE;
        final int oldAccess2 = oldAccess & ~compatibleChanges & ~accessPermissions;
        final int newAccess2 = newAccess & ~compatibleChanges & ~accessPermissions;
        return oldAccess2 != newAccess2;
    }
}

From source file:org.osjava.jardiff.Tools.java

License:Apache License

/**
 * Returns whether a method's newAccess is incompatible with oldAccess
 * following <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html">Java Language Specification, Java SE 7 Edition</a>:
 * <ul>// w w w . j  ava  2s  .  c o  m
 *   <li><a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.9">13.4.7 Access to Members and Constructors</a><ul>
 *     <li>Changing the declared access of a member or constructor to permit less access
 *        <b>may break compatibility</b> with pre-existing binaries, causing a linkage error to be thrown when these binaries are resolved.
 *     </li>
 *     <li>The binary format is defined so that changing a member or constructor to be more accessible does not cause a
 *         linkage error when a subclass (already) defines a method to have less access.
 *     </li>
 *     </ul></li>
 *   <li><a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.16">13.4.16 abstract Methods</a><ul>
 *     <li>Changing a method that is declared abstract to no longer be declared abstract
 *         <b>does not break compatibility</b> with pre-existing binaries.</li>
 *     <li>Changing a method that is not declared abstract to be declared abstract
 *         <b>will break compatibility</b> with pre-existing binaries that previously invoked the method, causing an AbstractMethodError.</li>
 *     </ul></li>
 *   <li><a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.17">13.4.17 final</a><ul>
 *     <li>Changing a method that is declared final to no longer be declared final
 *         <b>does not break compatibility</b> with pre-existing binaries.</li>
 *     <li>Changing an instance method that is not declared final to be declared final
 *         <b>may break compatibility</b> with existing binaries that depend on the ability to override the method.</li>
 *     <li>Changing a class (static) method that is not declared final to be declared final
 *         <b>does not break compatibility</b> with existing binaries, because the method could not have been overridden.</li>
 *     </ul></li>
 *   <li><a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.18">13.4.18 native Methods</a><ul>
 *     <li>Adding or deleting a native modifier of a method
 *         <b>does not break compatibility</b> with pre-existing binaries.</li>
 *     </ul></li>
 *   <li><a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.19">13.4.19 static Methods</a><ul>
 *     <li>If a method that is not declared private is also declared static (that is, a class method)
 *         and is changed to not be declared static (that is, to an instance method), or vice versa,
 *         then <i>compatibility with pre-existing binaries may be broken</i>, resulting in a linkage time error,
 *         namely an IncompatibleClassChangeError, if these methods are used by the pre-existing binaries.
 *         Such changes <b>break functional backward compatibility</b>!</li>
 *     </ul></li>
 *   <li><a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.20">13.4.20 synchronized Methods</a><ul>
 *     <li>Adding or deleting a synchronized modifier of a method
 *         <b>does not break compatibility</b> with pre-existing binaries.</li>
 *   </ul></li>
 *   <li><a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.21">13.4.21 Method and Constructor Throws</a><ul>
 *     <li>Changes to the throws clause of methods or constructors
 *         <b>do not break compatibility</b> with pre-existing binaries; these clauses are checked only at compile time.</li>
 *   </ul></li>
 * </ul>
 *
 * @param oldAccess
 * @param newAccess
 * @return
 */
public static boolean isMethodAccessChange(final int oldAccess, final int newAccess) {
    if (isAccessIncompatible(oldAccess, newAccess)) {
        return true; // 13.4.7
    }
    if (not(oldAccess, Opcodes.ACC_ABSTRACT) && has(newAccess, Opcodes.ACC_ABSTRACT)) {
        return true; // 13.4.16 #2
    } else if (not(oldAccess, Opcodes.ACC_FINAL) && not(oldAccess, Opcodes.ACC_STATIC)
            && has(newAccess, Opcodes.ACC_FINAL)) {
        return true; // 13.4.17 #2 excluding and #3
    } else {
        final int compatibleChanges = Opcodes.ACC_ABSTRACT | // 13.4.16 #1
                Opcodes.ACC_FINAL | // 13.4.17 #1
                Opcodes.ACC_NATIVE | // 13.4.18 #1
                Opcodes.ACC_SYNCHRONIZED; // 13.4.20 #1
        final int accessPermissions = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE;
        final int oldAccess2 = oldAccess & ~compatibleChanges & ~accessPermissions;
        final int newAccess2 = newAccess & ~compatibleChanges & ~accessPermissions;
        return oldAccess2 != newAccess2;
    }
}

From source file:org.osjava.jardiff.ToolsTest.java

License:Apache License

@Test
public void isClassAccessChange() {
    // A class can't become final.
    assertTrue(Tools.isClassAccessChange(0, Opcodes.ACC_FINAL));
    assertTrue(Tools.isClassAccessChange(0, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL));
    // ... but can become non-final.
    assertFalse(Tools.isClassAccessChange(Opcodes.ACC_FINAL, 0));
    assertFalse(Tools.isClassAccessChange(Opcodes.ACC_FINAL + Opcodes.ACC_PUBLIC, Opcodes.ACC_PUBLIC));

    // No matter the final access, can't become protected or private or
    // package if it was public.
    assertTrue(Tools.isClassAccessChange(Opcodes.ACC_FINAL + Opcodes.ACC_PUBLIC, 0));
    assertTrue(Tools.isClassAccessChange(Opcodes.ACC_PUBLIC, Opcodes.ACC_PROTECTED));
    // A class can become concrete.
    assertFalse(Tools.isClassAccessChange(Opcodes.ACC_ABSTRACT, 0));
    assertFalse(Tools.isClassAccessChange(Opcodes.ACC_ABSTRACT + Opcodes.ACC_PUBLIC, Opcodes.ACC_PUBLIC));
    assertFalse(Tools.isClassAccessChange(Opcodes.ACC_ABSTRACT + Opcodes.ACC_PROTECTED, Opcodes.ACC_PROTECTED));
    // ...but can't become abstract
    assertTrue(Tools.isClassAccessChange(0, Opcodes.ACC_ABSTRACT));
    assertTrue(Tools.isClassAccessChange(Opcodes.ACC_PUBLIC, Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT));
    assertTrue(Tools.isClassAccessChange(Opcodes.ACC_PROTECTED, Opcodes.ACC_PROTECTED + Opcodes.ACC_ABSTRACT));
}