1 /*
  2  * Copyright (c) 2007, 2015, 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 
 26 package com.sun.tools.classfile;
 27 
 28 import java.io.IOException;
 29 import java.util.LinkedHashSet;
 30 import 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  */
 40 public 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_IDENTITY      = 0x0020; // class, inner
 47     public static final int ACC_SYNCHRONIZED  = 0x0020; //                      method
 48     public static final int ACC_VALUE         = 0x0040; // class, inner,
 49     public static final int ACC_VOLATILE      = 0x0040; //               field
 50     public static final int ACC_BRIDGE        = 0x0040; //                      method
 51     public static final int ACC_TRANSIENT     = 0x0080; //               field
 52     public static final int ACC_VARARGS       = 0x0080; //                      method
 53     public static final int ACC_NATIVE        = 0x0100; //                      method
 54     public static final int ACC_INTERFACE     = 0x0200; // class, inner
 55     public static final int ACC_ABSTRACT      = 0x0400; // class, inner,        method
 56     public static final int ACC_PRIMITIVE     = 0x0800; //                      class
 57     public static final int ACC_STRICT        = 0x0800; //                      method, field
 58     public static final int ACC_SYNTHETIC     = 0x1000; // class, inner, field, method
 59     public static final int ACC_ANNOTATION    = 0x2000; // class, inner
 60     public static final int ACC_ENUM          = 0x4000; // class, inner, field
 61     public static final int ACC_MANDATED      = 0x8000; //                          method parameter
 62     public static final int ACC_MODULE        = 0x8000; // class
 63 
 64     public static enum Kind { Class, InnerClass, Field, Method}
 65 
 66     AccessFlags(ClassReader cr) throws IOException {
 67         this(cr.readUnsignedShort());
 68     }
 69 
 70     public AccessFlags(int flags) {
 71         this.flags = flags;
 72     }
 73 
 74     public AccessFlags ignore(int mask) {
 75         return new AccessFlags(flags & ~mask);
 76     }
 77 
 78     public boolean is(int mask) {
 79         return (flags & mask) != 0;
 80     }
 81 
 82     public int byteLength() {
 83         return 2;
 84     }
 85 
 86     private static final int[] classModifiers = {
 87         ACC_PUBLIC, ACC_FINAL, ACC_IDENTITY, ACC_ABSTRACT, ACC_PRIMITIVE, ACC_VALUE
 88     };
 89 
 90     private static final int[] classFlags = {
 91         ACC_PUBLIC, ACC_FINAL, ACC_IDENTITY, ACC_INTERFACE, ACC_ABSTRACT,
 92         ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE, ACC_PRIMITIVE, ACC_VALUE
 93     };
 94 
 95     public Set<String> getClassModifiers() {
 96         int f = ((flags & ACC_INTERFACE) != 0 ? flags & ~ACC_ABSTRACT : flags);
 97         return getModifiers(f, classModifiers, Kind.Class);
 98     }
 99 
100     public Set<String> getClassFlags() {
101         return getFlags(classFlags, Kind.Class);
102     }
103 
104     private static final int[] innerClassModifiers = {
105         ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_IDENTITY,
106         ACC_ABSTRACT, ACC_PRIMITIVE, ACC_VALUE
107     };
108 
109     private static final int[] innerClassFlags = {
110         ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_IDENTITY,
111         ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_PRIMITIVE, ACC_VALUE
112     };
113 
114     public Set<String> getInnerClassModifiers() {
115         int f = ((flags & ACC_INTERFACE) != 0 ? flags & ~ACC_ABSTRACT : flags);
116         return getModifiers(f, innerClassModifiers, Kind.InnerClass);
117     }
118 
119     public Set<String> getInnerClassFlags() {
120         return getFlags(innerClassFlags, Kind.InnerClass);
121     }
122 
123     private static final int[] fieldModifiers = {
124         ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
125         ACC_VOLATILE, ACC_TRANSIENT
126     };
127 
128     private static final int[] fieldFlags = {
129         ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
130         ACC_VOLATILE, ACC_TRANSIENT, ACC_SYNTHETIC, ACC_ENUM, ACC_STRICT
131     };
132 
133     public Set<String> getFieldModifiers() {
134         return getModifiers(fieldModifiers, Kind.Field);
135     }
136 
137     public Set<String> getFieldFlags() {
138         return getFlags(fieldFlags, Kind.Field);
139     }
140 
141     private static final int[] methodModifiers = {
142         ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
143         ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT
144     };
145 
146     private static final int[] methodFlags = {
147         ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
148         ACC_SYNCHRONIZED, ACC_BRIDGE, ACC_VARARGS, ACC_NATIVE, ACC_ABSTRACT,
149         ACC_STRICT, ACC_SYNTHETIC
150     };
151 
152     public Set<String> getMethodModifiers() {
153         return getModifiers(methodModifiers, Kind.Method);
154     }
155 
156     public Set<String> getMethodFlags() {
157         return getFlags(methodFlags, Kind.Method);
158     }
159 
160     private Set<String> getModifiers(int[] modifierFlags, Kind t) {
161         return getModifiers(flags, modifierFlags, t);
162     }
163 
164     private static Set<String> getModifiers(int flags, int[] modifierFlags, Kind t) {
165         Set<String> s = new LinkedHashSet<>();
166         for (int m: modifierFlags) {
167             if ((flags & m) != 0)
168                 s.add(flagToModifier(m, t));
169         }
170         return s;
171     }
172 
173     private Set<String> getFlags(int[] expectedFlags, Kind t) {
174         Set<String> s = new LinkedHashSet<>();
175         int f = flags;
176         for (int e: expectedFlags) {
177             if ((f & e) != 0) {
178                 s.add(flagToName(e, t));
179                 f = f & ~e;
180             }
181         }
182         while (f != 0) {
183             int bit = Integer.highestOneBit(f);
184             s.add("0x" + Integer.toHexString(bit));
185             f = f & ~bit;
186         }
187         return s;
188     }
189 
190     private static String flagToModifier(int flag, Kind t) {
191         switch (flag) {
192             case ACC_PUBLIC:
193                 return "public";
194             case ACC_PRIVATE:
195                 return "private";
196             case ACC_PROTECTED:
197                 return "protected";
198             case ACC_STATIC:
199                 return "static";
200             case ACC_FINAL:
201                 return "final";
202             case 0x20:
203                 return (t == Kind.Class || t == Kind.InnerClass) ? "identity" : "synchronized";
204             case 0x80:
205                 return (t == Kind.Field ? "transient" : null);
206             case ACC_VOLATILE:
207                 return "volatile";
208             case ACC_NATIVE:
209                 return "native";
210             case ACC_ABSTRACT:
211                 return "abstract";
212             case 0x800:
213                 return (t == Kind.Field) ? "strict" : "strictfp";
214             case ACC_MANDATED:
215                 return "mandated";
216             default:
217                 return null;
218         }
219     }
220 
221     private static String flagToName(int flag, Kind t) {
222         switch (flag) {
223         case ACC_PUBLIC:
224             return "ACC_PUBLIC";
225         case ACC_PRIVATE:
226             return "ACC_PRIVATE";
227         case ACC_PROTECTED:
228             return "ACC_PROTECTED";
229         case ACC_STATIC:
230             return "ACC_STATIC";
231         case ACC_FINAL:
232             return "ACC_FINAL";
233         case 0x20:
234             return ((t == Kind.Class || t == Kind.InnerClass) ? "ACC_IDENTITY" : "ACC_SYNCHRONIZED");
235         case 0x40:
236             return (t == Kind.Field ? "ACC_VOLATILE" : t == Kind.Method ? "ACC_BRIDGE" : "ACC_VALUE");
237         case 0x80:
238             return (t == Kind.Field ? "ACC_TRANSIENT" : "ACC_VARARGS");
239         case ACC_NATIVE:
240             return "ACC_NATIVE";
241         case ACC_INTERFACE:
242             return "ACC_INTERFACE";
243         case ACC_ABSTRACT:
244             return "ACC_ABSTRACT";
245         case ACC_STRICT:
246             return "ACC_STRICT";
247         case ACC_SYNTHETIC:
248             return "ACC_SYNTHETIC";
249         case ACC_ANNOTATION:
250             return "ACC_ANNOTATION";
251         case ACC_ENUM:
252             return "ACC_ENUM";
253         case 0x8000:
254             return (t == Kind.Class ? "ACC_MODULE" : "ACC_MANDATED");
255         default:
256             return null;
257         }
258     }
259 
260     public final int flags;
261 }