001: /*
002: * ProGuard -- shrinking, optimization, obfuscation, and preverification
003: * of Java bytecode.
004: *
005: * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the Free
009: * Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
015: * more details.
016: *
017: * You should have received a copy of the GNU General Public License along
018: * with this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: package proguard.obfuscate;
022:
023: import proguard.classfile.*;
024: import proguard.classfile.constant.*;
025: import proguard.classfile.constant.visitor.ConstantVisitor;
026: import proguard.classfile.util.*;
027:
028: /**
029: * This <code>ConstantVisitor</code> makes package visible classes and class
030: * members public, if they are referenced by visited references from different
031: * packages.
032: *
033: * @author Eric Lafortune
034: */
035: public class ClassOpener extends SimplifiedVisitor implements
036: ConstantVisitor {
037: // Implementations for ConstantVisitor.
038:
039: public void visitAnyConstant(Clazz clazz, Constant constant) {
040: }
041:
042: public void visitStringConstant(Clazz clazz,
043: StringConstant stringConstant) {
044: fixPackageVisibility(clazz, stringConstant.referencedClass,
045: stringConstant.referencedMember);
046: }
047:
048: public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) {
049: fixPackageVisibility(clazz, refConstant.referencedClass,
050: refConstant.referencedMember);
051: }
052:
053: public void visitClassConstant(Clazz clazz,
054: ClassConstant classConstant) {
055: // Do we know the referenced class?
056: Clazz referencedClass = classConstant.referencedClass;
057: if (referencedClass != null) {
058: int accessFlags = referencedClass.getAccessFlags();
059:
060: // Make it public if necessary.
061: if (isNotPublic(accessFlags)
062: && referencedClass instanceof ProgramClass
063: && inDifferentPackages(clazz, referencedClass)) {
064: ((ProgramClass) referencedClass).u2accessFlags = AccessUtil
065: .replaceAccessFlags(accessFlags,
066: ClassConstants.INTERNAL_ACC_PUBLIC);
067: }
068: }
069: }
070:
071: // Small utility methods.
072:
073: /**
074: * Fixes the package visibility of the given referenced class member,
075: * if necessary.
076: */
077: private void fixPackageVisibility(Clazz clazz,
078: Clazz referencedClass, Member referencedMember) {
079: // Do we know the referenced class member?
080: if (referencedMember != null) {
081: int accessFlags = referencedMember.getAccessFlags();
082:
083: // Make it public if necessary.
084: if (isNotPublic(accessFlags)
085: && referencedMember instanceof ProgramMember
086: && inDifferentPackages(clazz, referencedClass)) {
087: ((ProgramMember) referencedMember).u2accessFlags = AccessUtil
088: .replaceAccessFlags(
089: accessFlags,
090: clazz.extends_(referencedClass) ? ClassConstants.INTERNAL_ACC_PROTECTED
091: : ClassConstants.INTERNAL_ACC_PUBLIC);
092: }
093: }
094: }
095:
096: /**
097: * Returns whether the given classes are in different packages..
098: */
099: private boolean inDifferentPackages(Clazz class1, Clazz class2) {
100: return !ClassUtil.internalPackageName(class1.getName()).equals(
101: ClassUtil.internalPackageName(class2.getName()));
102: }
103:
104: /**
105: * Returns whether the given access flags specify a non-public class
106: * or class member.
107: */
108: private boolean isNotPublic(int accessFlags) {
109: return (accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) == 0;
110: }
111: }
|