1 /*
2  * Copyright (C) 2009 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 package com.android.mkstubs.sourcer;
18 
19 import org.objectweb.asm.Opcodes;
20 
21 /**
22  * Source generator for the access fields of methods, fields and classes.
23  * <p/>
24  * Given an integer access field and a type ({@link #IS_CLASS}, {@link #IS_FIELD} or
25  * {@link #IS_METHOD}), the {@link #write(int, int)} method can generate a string
26  * desribing the access modifiers for a Java source.
27  */
28 class AccessSourcer {
29 
30     private final Output mOutput;
31 
32     public static int IS_CLASS  = 1;
33     public static int IS_FIELD  = 2;
34     public static int IS_METHOD = 4;
35 
36     private enum Flag {
37         ACC_PUBLIC(Opcodes.ACC_PUBLIC               , IS_CLASS | IS_FIELD | IS_METHOD),
38         ACC_PRIVATE(Opcodes.ACC_PRIVATE             , IS_CLASS | IS_FIELD | IS_METHOD),
39         ACC_PROTECTED(Opcodes.ACC_PROTECTED         , IS_CLASS | IS_FIELD | IS_METHOD),
40         ACC_STATIC(Opcodes.ACC_STATIC               , IS_FIELD | IS_METHOD),
41         ACC_FINAL(Opcodes.ACC_FINAL                 , IS_CLASS | IS_FIELD | IS_METHOD),
42         ACC_SUPER(Opcodes.ACC_SUPER                 , IS_CLASS),
43         ACC_SYNCHRONIZED(Opcodes.ACC_SYNCHRONIZED   , IS_METHOD),
44         ACC_VOLATILE(Opcodes.ACC_VOLATILE           , IS_FIELD),
45         ACC_BRIDGE(Opcodes.ACC_BRIDGE               , IS_METHOD),
46         ACC_VARARGS(Opcodes.ACC_VARARGS             , IS_METHOD),
47         ACC_TRANSIENT(Opcodes.ACC_TRANSIENT         , IS_FIELD),
48         ACC_NATIVE(Opcodes.ACC_NATIVE               , IS_METHOD),
49         ACC_INTERFACE(Opcodes.ACC_INTERFACE         , IS_CLASS),
50         ACC_ABSTRACT(Opcodes.ACC_ABSTRACT           , IS_CLASS | IS_METHOD),
51         ACC_STRICT(Opcodes.ACC_STRICT               , IS_METHOD),
52         ACC_SYNTHETIC(Opcodes.ACC_SYNTHETIC         , IS_CLASS | IS_FIELD | IS_METHOD),
53         ACC_ANNOTATION(Opcodes.ACC_ANNOTATION       , IS_CLASS),
54         ACC_ENUM(Opcodes.ACC_ENUM                   , IS_CLASS),
55         ACC_DEPRECATED(Opcodes.ACC_DEPRECATED       , IS_CLASS | IS_FIELD | IS_METHOD)
56         ;
57 
58         private final int mValue;
59         private final int mFilter;
60 
Flag(int value, int filter)61         Flag(int value, int filter) {
62             mValue = value;
63             mFilter = filter;
64         }
65 
getValue()66         public int getValue() {
67             return mValue;
68         }
69 
getFilter()70         public int getFilter() {
71             return mFilter;
72         }
73 
74         /** Transforms "ACC_PUBLIC" into "public" */
75         @Override
toString()76         public String toString() {
77             return super.toString().substring(4).toLowerCase();
78         }
79     }
80 
81 
AccessSourcer(Output output)82     public AccessSourcer(Output output) {
83         mOutput = output;
84     }
85 
86     /**
87      * Generates a list of access keywords, e.g. "public final".
88      * <p/>
89      * It is up to the caller to filter extra keywords that should not be generated,
90      * e.g. {@link Flag#ACC_SYNTHETIC}.
91      *
92      * @param access The access mode, e.g. 33 or 18
93      * @param filter One of {@link #IS_CLASS}, {@link #IS_FIELD} or {@link #IS_METHOD}, which
94      *        indicates the validity context.
95      */
write(int access, int filter)96     public void write(int access, int filter) {
97 
98         boolean need_sep = false;
99 
100         for (Flag f : Flag.values()) {
101             if ((f.getFilter() & filter) != 0 && (access & f.getValue()) != 0) {
102                 if (need_sep) {
103                     mOutput.write(" ");
104                 }
105                 mOutput.write(f.toString());
106                 need_sep = true;
107             }
108         }
109 
110     }
111 }
112