AccessFlags.java revision 2942:08092deced3f
1/*
2 * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.tools.classfile;
27
28import java.io.IOException;
29import java.util.LinkedHashSet;
30import java.util.Set;
31
32/**
33 * See JVMS, sections 4.2, 4.6, 4.7.
34 *
35 *  <p><b>This is NOT part of any supported API.
36 *  If you write code that depends on this, you do so at your own risk.
37 *  This code and its internal interfaces are subject to change or
38 *  deletion without notice.</b>
39 */
40public class AccessFlags {
41    public static final int ACC_PUBLIC        = 0x0001; // class, inner, field, method
42    public static final int ACC_PRIVATE       = 0x0002; //        inner, field, method
43    public static final int ACC_PROTECTED     = 0x0004; //        inner, field, method
44    public static final int ACC_STATIC        = 0x0008; //        inner, field, method
45    public static final int ACC_FINAL         = 0x0010; // class, inner, field, method
46    public static final int ACC_SUPER         = 0x0020; // class
47    public static final int ACC_SYNCHRONIZED  = 0x0020; //                      method
48    public static final int ACC_VOLATILE      = 0x0040; //               field
49    public static final int ACC_BRIDGE        = 0x0040; //                      method
50    public static final int ACC_TRANSIENT     = 0x0080; //               field
51    public static final int ACC_VARARGS       = 0x0080; //                      method
52    public static final int ACC_NATIVE        = 0x0100; //                      method
53    public static final int ACC_INTERFACE     = 0x0200; // class, inner
54    public static final int ACC_ABSTRACT      = 0x0400; // class, inner,        method
55    public static final int ACC_STRICT        = 0x0800; //                      method
56    public static final int ACC_SYNTHETIC     = 0x1000; // class, inner, field, method
57    public static final int ACC_ANNOTATION    = 0x2000; // class, inner
58    public static final int ACC_ENUM          = 0x4000; // class, inner, field
59    public static final int ACC_MANDATED      = 0x8000; // class, inner, field, method
60
61    public static enum Kind { Class, InnerClass, Field, Method}
62
63    AccessFlags(ClassReader cr) throws IOException {
64        this(cr.readUnsignedShort());
65    }
66
67    public AccessFlags(int flags) {
68        this.flags = flags;
69    }
70
71    public AccessFlags ignore(int mask) {
72        return new AccessFlags(flags & ~mask);
73    }
74
75    public boolean is(int mask) {
76        return (flags & mask) != 0;
77    }
78
79    public int byteLength() {
80        return 2;
81    }
82
83    private static final int[] classModifiers = {
84        ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT
85    };
86
87    private static final int[] classFlags = {
88        ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT,
89        ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM
90    };
91
92    public Set<String> getClassModifiers() {
93        int f = ((flags & ACC_INTERFACE) != 0 ? flags & ~ACC_ABSTRACT : flags);
94        return getModifiers(f, classModifiers, Kind.Class);
95    }
96
97    public Set<String> getClassFlags() {
98        return getFlags(classFlags, Kind.Class);
99    }
100
101    private static final int[] innerClassModifiers = {
102        ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
103        ACC_ABSTRACT
104    };
105
106    private static final int[] innerClassFlags = {
107        ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SUPER,
108        ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM
109    };
110
111    public Set<String> getInnerClassModifiers() {
112        int f = ((flags & ACC_INTERFACE) != 0 ? flags & ~ACC_ABSTRACT : flags);
113        return getModifiers(f, innerClassModifiers, Kind.InnerClass);
114    }
115
116    public Set<String> getInnerClassFlags() {
117        return getFlags(innerClassFlags, Kind.InnerClass);
118    }
119
120    private static final int[] fieldModifiers = {
121        ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
122        ACC_VOLATILE, ACC_TRANSIENT
123    };
124
125    private static final int[] fieldFlags = {
126        ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
127        ACC_VOLATILE, ACC_TRANSIENT, ACC_SYNTHETIC, ACC_ENUM
128    };
129
130    public Set<String> getFieldModifiers() {
131        return getModifiers(fieldModifiers, Kind.Field);
132    }
133
134    public Set<String> getFieldFlags() {
135        return getFlags(fieldFlags, Kind.Field);
136    }
137
138    private static final int[] methodModifiers = {
139        ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
140        ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT
141    };
142
143    private static final int[] methodFlags = {
144        ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
145        ACC_SYNCHRONIZED, ACC_BRIDGE, ACC_VARARGS, ACC_NATIVE, ACC_ABSTRACT,
146        ACC_STRICT, ACC_SYNTHETIC
147    };
148
149    public Set<String> getMethodModifiers() {
150        return getModifiers(methodModifiers, Kind.Method);
151    }
152
153    public Set<String> getMethodFlags() {
154        return getFlags(methodFlags, Kind.Method);
155    }
156
157    private Set<String> getModifiers(int[] modifierFlags, Kind t) {
158        return getModifiers(flags, modifierFlags, t);
159    }
160
161    private static Set<String> getModifiers(int flags, int[] modifierFlags, Kind t) {
162        Set<String> s = new LinkedHashSet<>();
163        for (int m: modifierFlags) {
164            if ((flags & m) != 0)
165                s.add(flagToModifier(m, t));
166        }
167        return s;
168    }
169
170    private Set<String> getFlags(int[] expectedFlags, Kind t) {
171        Set<String> s = new LinkedHashSet<>();
172        int f = flags;
173        for (int e: expectedFlags) {
174            if ((f & e) != 0) {
175                s.add(flagToName(e, t));
176                f = f & ~e;
177            }
178        }
179        while (f != 0) {
180            int bit = Integer.highestOneBit(f);
181            s.add("0x" + Integer.toHexString(bit));
182            f = f & ~bit;
183        }
184        return s;
185    }
186
187    private static String flagToModifier(int flag, Kind t) {
188        switch (flag) {
189            case ACC_PUBLIC:
190                return "public";
191            case ACC_PRIVATE:
192                return "private";
193            case ACC_PROTECTED:
194                return "protected";
195            case ACC_STATIC:
196                return "static";
197            case ACC_FINAL:
198                return "final";
199            case ACC_SYNCHRONIZED:
200                return "synchronized";
201            case 0x80:
202                return (t == Kind.Field ? "transient" : null);
203            case ACC_VOLATILE:
204                return "volatile";
205            case ACC_NATIVE:
206                return "native";
207            case ACC_ABSTRACT:
208                return "abstract";
209            case ACC_STRICT:
210                return "strictfp";
211            case ACC_MANDATED:
212                return "mandated";
213            default:
214                return null;
215        }
216    }
217
218    private static String flagToName(int flag, Kind t) {
219        switch (flag) {
220        case ACC_PUBLIC:
221            return "ACC_PUBLIC";
222        case ACC_PRIVATE:
223            return "ACC_PRIVATE";
224        case ACC_PROTECTED:
225            return "ACC_PROTECTED";
226        case ACC_STATIC:
227            return "ACC_STATIC";
228        case ACC_FINAL:
229            return "ACC_FINAL";
230        case 0x20:
231            return (t == Kind.Class ? "ACC_SUPER" : "ACC_SYNCHRONIZED");
232        case 0x40:
233            return (t == Kind.Field ? "ACC_VOLATILE" : "ACC_BRIDGE");
234        case 0x80:
235            return (t == Kind.Field ? "ACC_TRANSIENT" : "ACC_VARARGS");
236        case ACC_NATIVE:
237            return "ACC_NATIVE";
238        case ACC_INTERFACE:
239            return "ACC_INTERFACE";
240        case ACC_ABSTRACT:
241            return "ACC_ABSTRACT";
242        case ACC_STRICT:
243            return "ACC_STRICT";
244        case ACC_SYNTHETIC:
245            return "ACC_SYNTHETIC";
246        case ACC_ANNOTATION:
247            return "ACC_ANNOTATION";
248        case ACC_ENUM:
249            return "ACC_ENUM";
250        case ACC_MANDATED:
251            return "ACC_MANDATED";
252        default:
253            return null;
254        }
255    }
256
257    public final int flags;
258}
259