OSDN Git Service

a98bef05220f8b860f005720eb3a1102dbc21fdf
[stigmata/stigmata-core.git] / src / main / java / jp / sourceforge / stigmata / utils / WellknownClassManager.java
1 package jp.sourceforge.stigmata.utils;
2
3 import java.util.ArrayList;
4 import java.util.Iterator;
5 import java.util.List;
6
7 import jp.sourceforge.stigmata.utils.WellknownClassJudgeRule.MatchPartType;
8 import jp.sourceforge.stigmata.utils.WellknownClassJudgeRule.MatchType;
9
10 /**
11  * Managing wellknown class checking rule.
12  * 
13  * @author Haruaki TAMADA
14  */
15 public class WellknownClassManager implements Iterable<WellknownClassJudgeRule>{
16     private List<WellknownClassJudgeRule> rules = new ArrayList<WellknownClassJudgeRule>();
17
18     /**
19      * public field/method flag defined in JVM specification.
20      */
21     private static final int OPCODE_ACC_PUBLIC = 1;
22     /**
23      * private field/method flag defined in JVM specification.
24      */
25     @SuppressWarnings("unused")
26     private static final int OPCODE_ACC_PRIVATE = 2;
27     /**
28      * protected field/method flag defined in JVM specification.
29      */
30     @SuppressWarnings("unused")
31     private static final int OPCODE_ACC_PROTECTED = 4;
32     /**
33      * static field/method flag defined in JVM specification.
34      */
35     private static final int OPCODE_ACC_STATIC = 8;
36     /**
37      * final field/method flag defined in JVM specification.
38      */
39     private static final int OPCODE_ACC_FINAL = 16;
40
41     /**
42      * default constructor.
43      */
44     public WellknownClassManager(){
45     }
46
47     /**
48      * constructor with parent WellknownClassManager.
49      */
50     public WellknownClassManager(WellknownClassManager manager){
51         rules = new ArrayList<WellknownClassJudgeRule>(manager.rules);
52     }
53
54     public void remove(WellknownClassJudgeRule rule){
55         rules.remove(rule);
56     }
57
58     public void remove(String value, MatchType matchType, MatchPartType partType){
59         remove(new WellknownClassJudgeRule(value, matchType, partType));
60     }
61
62     public void clear(){
63         rules.clear();
64     }
65
66     @Override
67     public synchronized Iterator<WellknownClassJudgeRule> iterator(){
68         List<WellknownClassJudgeRule> copiedRules = new ArrayList<WellknownClassJudgeRule>(rules);
69         return copiedRules.iterator();
70     }
71
72     public synchronized WellknownClassJudgeRule[] getRules(){
73         return rules.toArray(new WellknownClassJudgeRule[rules.size()]);
74     }
75
76     public void add(WellknownClassJudgeRule rule){
77         if(!rules.contains(rule)){
78             rules.add(rule);
79         }
80     }
81
82     private boolean checkSystemClass(String className){
83         FullyClassName name = new FullyClassName(className);
84         if(isMatch(name, true)){
85             return false;
86         }
87         return isMatch(name, false);
88     }
89
90     private boolean isMatch(FullyClassName name, boolean excludeFlag){
91         for(Iterator<WellknownClassJudgeRule> i = rules.iterator(); i.hasNext(); ){
92             WellknownClassJudgeRule s = i.next();
93             if(s.isExclude() == excludeFlag){
94                 boolean flag = false;
95                 String partName = name.getFullyName();
96                 if(s.getMatchPartType() == MatchPartType.CLASS_NAME){
97                     partName = name.getClassName();
98                 }
99                 else if(s.getMatchPartType() == MatchPartType.PACKAGE_NAME){
100                     partName = name.getPackageName();
101                 }
102                 switch(s.getMatchType()){
103                 case PREFIX:
104                     flag = partName.startsWith(s.getPattern());
105                     break;
106                 case SUFFIX:
107                     flag = partName.endsWith(s.getPattern());
108                     break;
109                 case EXACT:
110                     flag = partName.equals(s.getPattern());
111                     break;
112                 case NOT_MATCH:
113                     flag = !partName.equals(s.getPattern());
114                     break;
115                 }
116                 if(flag){
117                     return flag;
118                 }
119             }
120         }
121         return false;
122     }
123
124     /**
125      * check system defined methods, which are following methods.
126      * <ul>
127      *   <li><code>public static void main(String[])</code></li>
128      *   <li><code>static void &lt;clinit&gt;(void)</code>(static initializer)</li>
129      *   <li><code>void &lt;init&gt;</code>(constructor)</li>
130      * </ul>
131      */
132     private boolean checkSystemMethod(int access, String methodName, String signature){
133         if(methodName.equals("main")){
134             return signature.equals("([Ljava/lang/String;)V")
135                 && checkAccess(access, OPCODE_ACC_PUBLIC);
136         }
137         else if(methodName.equals("<clinit>")){
138             return signature.equals("()V")
139                 && checkAccess(access, OPCODE_ACC_STATIC);
140         }
141         else if(methodName.equals("<init>")){
142             return !checkAccess(access, OPCODE_ACC_STATIC);
143         }
144         return false;
145     }
146
147     /**
148      * check system defined field, which is following field.
149      * <ul>
150      *   <code>static final long serialVersionUID</code>
151      * </ul>
152      */
153     private boolean checkSystemField(int access, String fieldName, String signature){
154         if(fieldName.equals("serialVersionUID")){
155             return checkAccess(access, OPCODE_ACC_STATIC) &&
156                 checkAccess(access, OPCODE_ACC_FINAL) &&
157                 signature.equals("J");
158         }
159
160         return false;
161     }
162
163     public boolean isWellKnownClass(String className){
164         return checkSystemClass(className);
165     }
166
167     public boolean isSystemMethod(int access, String methodName, String signature){
168         return checkSystemMethod(access, methodName, signature);
169     }
170
171     public boolean isSystemField(int access, String fieldName, String signature){
172         return checkSystemField(access, fieldName, signature);
173     }
174
175     private boolean checkAccess(int access, int code){
176         return (access & code) == code;
177     }
178 }