001    /*
002     * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.classfile;
027    
028    import java.io.IOException;
029    import java.util.LinkedHashSet;
030    import java.util.Set;
031    
032    /**
033     * See JVMS3, sections 4.2, 4.6, 4.7.
034     *
035     *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
036     *  you write code that depends on this, you do so at your own risk.
037     *  This code and its internal interfaces are subject to change or
038     *  deletion without notice.</b>
039     */
040    public class AccessFlags {
041        public static final int ACC_PUBLIC        = 0x0001; // class, inner, field, method
042        public static final int ACC_PRIVATE       = 0x0002; //        inner, field, method
043        public static final int ACC_PROTECTED     = 0x0004; //        inner, field, method
044        public static final int ACC_STATIC        = 0x0008; //        inner, field, method
045        public static final int ACC_FINAL         = 0x0010; // class, inner, field, method
046        public static final int ACC_SUPER         = 0x0020; // class
047        public static final int ACC_SYNCHRONIZED  = 0x0020; //                      method
048        public static final int ACC_VOLATILE      = 0x0040; //               field
049        public static final int ACC_BRIDGE        = 0x0040; //                      method
050        public static final int ACC_TRANSIENT     = 0x0080; //               field
051        public static final int ACC_VARARGS       = 0x0080; //                      method
052        public static final int ACC_NATIVE        = 0x0100; //                      method
053        public static final int ACC_INTERFACE     = 0x0200; // class, inner
054        public static final int ACC_ABSTRACT      = 0x0400; // class, inner,        method
055        public static final int ACC_STRICT        = 0x0800; //                      method
056        public static final int ACC_SYNTHETIC     = 0x1000; // class, inner, field, method
057        public static final int ACC_ANNOTATION    = 0x2000; // class, inner
058        public static final int ACC_ENUM          = 0x4000; // class, inner, field
059        public static final int ACC_MODULE        = 0x8000; // class, inner, field, method
060    
061        private static enum Type { Class, InnerClass, Field, Method};
062    
063        AccessFlags(ClassReader cr) throws IOException {
064            this(cr.readUnsignedShort());
065        }
066    
067        public AccessFlags(int flags) {
068            this.flags = flags;
069        }
070    
071        public AccessFlags ignore(int mask) {
072            return new AccessFlags(flags & ~mask);
073        }
074    
075        public boolean is(int mask) {
076            return (flags & mask) != 0;
077        }
078    
079        private static final int[] classModifiers = {
080            ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT, ACC_MODULE
081        };
082    
083        private static final int[] classFlags = {
084            ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT,
085            ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE
086        };
087    
088        public Set<String> getClassModifiers() {
089            int f = ((flags & ACC_INTERFACE) != 0 ? flags & ~ACC_ABSTRACT : flags);
090            return getModifiers(f, classModifiers, Type.Class);
091        }
092    
093        public Set<String> getClassFlags() {
094            return getFlags(classFlags, Type.Class);
095        }
096    
097        private static final int[] innerClassModifiers = {
098            ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
099            ACC_ABSTRACT, ACC_MODULE
100        };
101    
102        private static final int[] innerClassFlags = {
103            ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SUPER,
104            ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE
105        };
106    
107        public Set<String> getInnerClassModifiers() {
108            int f = ((flags & ACC_INTERFACE) != 0 ? flags & ~ACC_ABSTRACT : flags);
109            return getModifiers(f, innerClassModifiers, Type.InnerClass);
110        }
111    
112        public Set<String> getInnerClassFlags() {
113            return getFlags(innerClassFlags, Type.InnerClass);
114        }
115    
116        private static final int[] fieldModifiers = {
117            ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
118            ACC_VOLATILE, ACC_TRANSIENT, ACC_MODULE
119        };
120    
121        private static final int[] fieldFlags = {
122            ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
123            ACC_VOLATILE, ACC_TRANSIENT, ACC_SYNTHETIC, ACC_ENUM, ACC_MODULE
124        };
125    
126        public Set<String> getFieldModifiers() {
127            return getModifiers(fieldModifiers, Type.Field);
128        }
129    
130        public Set<String> getFieldFlags() {
131            return getFlags(fieldFlags, Type.Field);
132        }
133    
134        private static final int[] methodModifiers = {
135            ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
136            ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT, ACC_MODULE
137        };
138    
139        private static final int[] methodFlags = {
140            ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
141            ACC_SYNCHRONIZED, ACC_BRIDGE, ACC_VARARGS, ACC_NATIVE, ACC_ABSTRACT,
142            ACC_STRICT, ACC_SYNTHETIC, ACC_MODULE
143        };
144    
145        public Set<String> getMethodModifiers() {
146            return getModifiers(methodModifiers, Type.Method);
147        }
148    
149        public Set<String> getMethodFlags() {
150            return getFlags(methodFlags, Type.Method);
151        }
152    
153        private Set<String> getModifiers(int[] modifierFlags, Type t) {
154            return getModifiers(flags, modifierFlags, t);
155        }
156    
157        private static Set<String> getModifiers(int flags, int[] modifierFlags, Type t) {
158            Set<String> s = new LinkedHashSet<String>();
159            for (int m: modifierFlags) {
160                if ((flags & m) != 0)
161                    s.add(flagToModifier(m, t));
162            }
163            return s;
164        }
165    
166        private Set<String> getFlags(int[] expectedFlags, Type t) {
167            Set<String> s = new LinkedHashSet<String>();
168            int f = flags;
169            for (int e: expectedFlags) {
170                if ((f & e) != 0) {
171                    s.add(flagToName(e, t));
172                    f = f & ~e;
173                }
174            }
175            while (f != 0) {
176                int bit = Integer.highestOneBit(f);
177                s.add("0x" + Integer.toHexString(bit));
178                f = f & ~bit;
179            }
180            return s;
181        }
182    
183        private static String flagToModifier(int flag, Type t) {
184            switch (flag) {
185                case ACC_PUBLIC:
186                    return "public";
187                case ACC_PRIVATE:
188                    return "private";
189                case ACC_PROTECTED:
190                    return "protected";
191                case ACC_STATIC:
192                    return "static";
193                case ACC_FINAL:
194                    return "final";
195                case ACC_SYNCHRONIZED:
196                    return "synchronized";
197                case 0x80:
198                    return (t == Type.Field ? "transient" : null);
199                case ACC_VOLATILE:
200                    return "volatile";
201                case ACC_NATIVE:
202                    return "native";
203                case ACC_ABSTRACT:
204                    return "abstract";
205                case ACC_STRICT:
206                    return "strictfp";
207                case ACC_MODULE:
208                    return "module";
209                default:
210                    return null;
211            }
212        }
213    
214        private static String flagToName(int flag, Type t) {
215            switch (flag) {
216            case ACC_PUBLIC:
217                return "ACC_PUBLIC";
218            case ACC_PRIVATE:
219                return "ACC_PRIVATE";
220            case ACC_PROTECTED:
221                return "ACC_PROTECTED";
222            case ACC_STATIC:
223                return "ACC_STATIC";
224            case ACC_FINAL:
225                return "ACC_FINAL";
226            case 0x20:
227                return (t == Type.Class ? "ACC_SUPER" : "ACC_SYNCHRONIZED");
228            case 0x40:
229                return (t == Type.Field ? "ACC_VOLATILE" : "ACC_BRIDGE");
230            case 0x80:
231                return (t == Type.Field ? "ACC_TRANSIENT" : "ACC_VARARGS");
232            case ACC_NATIVE:
233                return "ACC_NATIVE";
234            case ACC_INTERFACE:
235                return "ACC_INTERFACE";
236            case ACC_ABSTRACT:
237                return "ACC_ABSTRACT";
238            case ACC_STRICT:
239                return "ACC_STRICT";
240            case ACC_SYNTHETIC:
241                return "ACC_SYNTHETIC";
242            case ACC_ANNOTATION:
243                return "ACC_ANNOTATION";
244            case ACC_ENUM:
245                return "ACC_ENUM";
246            case ACC_MODULE:
247                return "ACC_MODULE";
248            default:
249                return null;
250            }
251        }
252    
253        final int flags;
254    }