1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // These classes are to check the additional flags for inner classes.
18 class A {
19   private static class B {
20   }
21   protected static interface C {
22   }
23 }
24 
25 public class Main {
26   public final static int INTERFACE_DEFINED_BITS =
27       0x0001 |  // public, may be set.
28       0x0002 |  // private, may be flagged by inner class.
29       0x0004 |  // protected, may be flagged by inner class.
30       0x0008 |  // static, may be flagged by inner class.
31       0x0010 |  // final, must not be set.
32       0x0020 |  // super, must not be set.
33       0x0200 |  // interface, must be set.
34       0x0400 |  // abstract, must be set.
35       0x1000 |  // synthetic, may be set.
36       0x2000 |  // annotation, may be set (annotation implies interface)
37       0x4000 ;  // enum, must not be set.
38 
39   public final static int CLASS_DEFINED_BITS =
40       0x0001 |  // public, may be set.
41       0x0002 |  // private, may be flagged by inner class.
42       0x0004 |  // protected, may be flagged by inner class.
43       0x0008 |  // static, may be flagged by inner class.
44       0x0010 |  // final, may be set.
45       0x0020 |  // super, may be set.
46       0x0200 |  // interface, must not be set.
47       0x0400 |  // abstract, may be set.
48       0x1000 |  // synthetic, may be set.
49       0x2000 |  // annotation, must not be set.
50       0x4000 ;  // enum, may be set.
51 
52   public final static int FIELD_DEFINED_BITS =
53        0x0001 |  // public
54        0x0002 |  // private
55        0x0004 |  // protected
56        0x0008 |  // static
57        0x0010 |  // final
58        0x0040 |  // volatile
59        0x0080 |  // transient
60        0x1000 |  // synthetic
61        0x4000 ;  // enum
62 
63   public final static int METHOD_DEFINED_BITS =
64        0x0001 |  // public
65        0x0002 |  // private
66        0x0004 |  // protected
67        0x0008 |  // static
68        0x0010 |  // final
69        0x0020 |  // synchronized
70        0x0040 |  // bridge
71        0x0080 |  // varargs
72        0x0100 |  // native
73        0x0400 |  // abstract
74        0x0800 |  // strictfp
75        0x1000 ;  // synthetic
76 
main(String args[])77   public static void main(String args[]) throws Exception {
78     check("Inf");
79     check("NonInf");
80     check("A");
81     check("A$B");
82   }
83 
check(String className)84   private static void check(String className) throws Exception {
85     Class<?> clazz = Class.forName(className);
86     if (className.equals("Inf")) {
87       if (!clazz.isInterface()) {
88         throw new RuntimeException("Expected an interface.");
89       }
90       int undefinedBits = 0xFFFF ^ INTERFACE_DEFINED_BITS;
91       if ((clazz.getModifiers() & undefinedBits) != 0) {
92         System.out.println("Clazz.getModifiers(): " + Integer.toBinaryString(clazz.getModifiers()));
93         System.out.println("INTERFACE_DEF_BITS: " + Integer.toBinaryString(INTERFACE_DEFINED_BITS));
94         throw new RuntimeException("Undefined bits for an interface: " + className);
95       }
96     } else {
97       if (clazz.isInterface()) {
98         throw new RuntimeException("Expected a class.");
99       }
100       int undefinedBits = 0xFFFF ^ CLASS_DEFINED_BITS;
101       if ((clazz.getModifiers() & undefinedBits) != 0) {
102         System.out.println("Clazz.getModifiers(): " + Integer.toBinaryString(clazz.getModifiers()));
103         System.out.println("CLASS_DEF_BITS: " + Integer.toBinaryString(CLASS_DEFINED_BITS));
104         throw new RuntimeException("Undefined bits for a class: " + className);
105       }
106     }
107 
108     // Check fields.
109     for (java.lang.reflect.Field f : clazz.getDeclaredFields()) {
110       String name = f.getName();
111       int undefinedBits = 0xFFFF ^ FIELD_DEFINED_BITS;
112       if ((f.getModifiers() & undefinedBits) != 0) {
113         System.out.println("f.getModifiers(): " + Integer.toBinaryString(f.getModifiers()));
114         System.out.println("FIELD_DEF_BITS: " + Integer.toBinaryString(FIELD_DEFINED_BITS));
115         throw new RuntimeException("Unexpected field bits: " + name);
116       }
117       if (name.equals("I")) {
118         // Interface field, just check generically.
119       } else {
120         // Check the name, see that the corresponding bit is set.
121         int bitmask = getFieldMask(name);
122         if ((bitmask & f.getModifiers()) == 0) {
123           throw new RuntimeException("Expected field bit not set.");
124         }
125       }
126     }
127 
128     // Check methods.
129     for (java.lang.reflect.Method m : clazz.getDeclaredMethods()) {
130       String name = m.getName();
131       int undefinedBits = 0xFFFF ^ METHOD_DEFINED_BITS;
132       if ((m.getModifiers() & undefinedBits) != 0) {
133           System.out.println("m.getModifiers(): " + Integer.toBinaryString(m.getModifiers()));
134           System.out.println("METHOD_DEF_BITS: " + Integer.toBinaryString(METHOD_DEFINED_BITS));
135         throw new RuntimeException("Unexpected method bits: " + name);
136       }
137       // Check the name, see that the corresponding bit is set.
138       int bitmask = getMethodMask(name);
139       if ((bitmask & m.getModifiers()) == 0) {
140         throw new RuntimeException("Expected method bit not set.");
141       }
142     }
143   }
144 
getFieldMask(String name)145   private static int getFieldMask(String name) {
146     int index = name.indexOf("Field");
147     if (index > 0) {
148       String shortS = name.substring(0, index);
149       if (shortS.equals("public")) {
150         return 0x0001;
151       }
152       if (shortS.equals("private")) {
153         return 0x0002;
154       }
155       if (shortS.equals("protected")) {
156         return 0x0004;
157       }
158       if (shortS.equals("static")) {
159         return 0x0008;
160       }
161       if (shortS.equals("transient")) {
162         return 0x0080;
163       }
164       if (shortS.equals("volatile")) {
165         return 0x0040;
166       }
167       if (shortS.equals("final")) {
168         return 0x0010;
169       }
170     }
171     throw new RuntimeException("Unexpected field name " + name);
172   }
173 
getMethodMask(String name)174   private static int getMethodMask(String name) {
175     int index = name.indexOf("Method");
176     if (index > 0) {
177       String shortS = name.substring(0, index);
178       if (shortS.equals("public")) {
179         return 0x0001;
180       }
181       if (shortS.equals("private")) {
182         return 0x0002;
183       }
184       if (shortS.equals("protected")) {
185         return 0x0004;
186       }
187       if (shortS.equals("static")) {
188         return 0x0008;
189       }
190       if (shortS.equals("synchronized")) {
191         return 0x0020;
192       }
193       if (shortS.equals("varargs")) {
194         return 0x0080;
195       }
196       if (shortS.equals("final")) {
197         return 0x0010;
198       }
199       if (shortS.equals("native")) {
200         return 0x0100;
201       }
202       if (shortS.equals("abstract")) {
203         return 0x0400;
204       }
205       if (shortS.equals("strictfp")) {
206         return 0x0800;
207       }
208     }
209     throw new RuntimeException("Unexpected method name " + name);
210   }
211 }
212