KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > obfuscator > modules > ModifierMatcher


1 /* ModifierMatcher Copyright (C) 1999-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; see the file COPYING. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: ModifierMatcher.java.in,v 1.2.2.2 2002/05/28 17:34:17 hoenicke Exp $
18  */

19
20 package jode.obfuscator.modules;
21 import jode.obfuscator.IdentifierMatcher;
22 import jode.obfuscator.Identifier;
23 import jode.obfuscator.ClassIdentifier;
24 import jode.obfuscator.FieldIdentifier;
25 import jode.obfuscator.MethodIdentifier;
26 import jode.obfuscator.OptionHandler;
27
28 import java.lang.reflect.Modifier JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.Iterator JavaDoc;
31
32 public class ModifierMatcher implements IdentifierMatcher, OptionHandler, Cloneable JavaDoc {
33     static final int PUBLIC = Modifier.PUBLIC;
34     static final int PROTECTED = Modifier.PROTECTED;
35     static final int PRIVATE = Modifier.PRIVATE;
36
37     int[] andMasks;
38     int[] xorMasks;
39
40     public static ModifierMatcher denyAll = new ModifierMatcher(new int[0],
41                                  new int[0]);
42     public static ModifierMatcher allowAll = new ModifierMatcher(0, 0);
43
44     /* Invariants:
45      * \forall i: ~andMasks[i] & xorMasks[i] == 0
46      * \forall i: entries wo. i does not imply entry nr. i
47      */

48
49     public ModifierMatcher() {
50     this(0,0);
51     }
52
53     private ModifierMatcher(int[] ands, int[] xors) {
54     andMasks = ands;
55     xorMasks = xors;
56     }
57
58     public ModifierMatcher(int and, int xor) {
59     andMasks = new int[] { and };
60     xorMasks = new int[] { xor };
61     }
62
63     public void setOption(String JavaDoc option, Collection JavaDoc values) {
64     ModifierMatcher mm = this;
65     if (option.equals("access")) {
66         for(Iterator JavaDoc i = values.iterator(); i.hasNext();) {
67         String JavaDoc str = (String JavaDoc) i.next();
68         boolean less = str.charAt(0) == '<';
69         boolean greater = str.charAt(0) == '>';
70         if (less || greater)
71             str = str.substring(1);
72         str = str.toUpperCase();
73         if (less) {
74             int access =
75             str.equals("PROTECTED") ? PUBLIC
76             : str.equals("PACKAGE") ? PROTECTED
77             : str.equals("PRIVATE") ? 0
78             : -1;
79             if (access == -1)
80             throw new IllegalArgumentException JavaDoc
81                 ("Unknown access modifier " + str);
82
83             mm = mm.forbidAccess(access, true);
84         } else {
85             int access =
86             str.equals("PUBLIC") ? PUBLIC
87             : str.equals("PROTECTED") ? PROTECTED
88             : str.equals("PACKAGE") ? 0
89             : str.equals("PRIVATE") ? PRIVATE
90             : -1;
91             if (access == -1)
92             throw new IllegalArgumentException JavaDoc
93                 ("Unknown access " + str);
94             mm = mm.forceAccess(access, greater);
95         }
96         }
97     } else if (option.equals("modifier")) {
98         for(Iterator JavaDoc i = values.iterator(); i.hasNext();) {
99         String JavaDoc str = (String JavaDoc) i.next();
100         boolean negate = str.charAt(0) == '!';
101         if (negate)
102             str = str.substring(1);
103         str = str.toUpperCase();
104
105         int modif =
106             str.equals("ABSTRACT") ? Modifier.ABSTRACT
107             : str.equals("FINAL") ? Modifier.FINAL
108             : str.equals("INTERFACE") ? Modifier.INTERFACE
109             : str.equals("NATIVE") ? Modifier.NATIVE
110             : str.equals("STATIC") ? Modifier.STATIC
111 ///#ifdef JDK12
112
: str.equals("STRICT") ? Modifier.STRICT
113 ///#endif
114
: str.equals("SYNCHRONIZED") ? Modifier.SYNCHRONIZED
115             : str.equals("TRANSIENT") ? Modifier.TRANSIENT
116             : str.equals("VOLATILE") ? Modifier.VOLATILE
117             : -1;
118         if (modif == -1)
119             throw new IllegalArgumentException JavaDoc
120             ("Unknown modifier " + str);
121         if (negate)
122             mm = mm.forbidModifier(modif);
123         else
124             mm = mm.forceModifier(modif);
125         }
126     } else
127         throw new IllegalArgumentException JavaDoc("Invalid option `"+option+"'.");
128     andMasks = mm.andMasks;
129     xorMasks = mm.xorMasks;
130     }
131
132     private static boolean implies(int and1, int xor1, int and2, int xor2) {
133     return ((and1 & and2) == and2 && (xor1 & and2) == xor2);
134     }
135
136     private boolean implies(int and, int xor) {
137     for (int i=0; i < andMasks.length; i++) {
138         if (!implies(andMasks[i], xorMasks[i], and, xor))
139         return false;
140     }
141     return true;
142     }
143     
144     private boolean impliedBy(int and, int xor) {
145     for (int i=0; i< andMasks.length; i++) {
146         if (implies(and, xor, andMasks[i], xorMasks[i]))
147         return true;
148     }
149     return false;
150     }
151
152     private boolean implies(ModifierMatcher mm) {
153     for (int i=0; i < andMasks.length; i++) {
154         if (!mm.impliedBy(andMasks[i], xorMasks[i]))
155         return false;
156     }
157     return true;
158     }
159
160     public ModifierMatcher and(ModifierMatcher mm) {
161     if (implies(mm))
162         return this;
163     if (mm.implies(this))
164         return mm;
165
166     ModifierMatcher result = denyAll;
167     for (int i=0; i< andMasks.length; i++)
168         result = result.or(mm.and(andMasks[i], xorMasks[i]));
169     return result;
170     }
171
172     public ModifierMatcher or(ModifierMatcher mm) {
173     if (implies(mm))
174         return mm;
175     if (mm.implies(this))
176         return this;
177     ModifierMatcher result = this;
178     for (int i=0; i < mm.andMasks.length; i++)
179         result = result.or(mm.andMasks[i], mm.xorMasks[i]);
180     return result;
181     }
182
183     private ModifierMatcher and(int and, int xor) {
184     if (this.implies(and, xor))
185         return this;
186     int newCount = 0;
187     next_i:
188     for (int i=0; i < andMasks.length; i++) {
189         if (implies(and, xor, andMasks[i], xorMasks[i]))
190         continue next_i;
191
192         for (int j=0; j < andMasks.length; j++) {
193         if (j != i
194             && implies(and | andMasks[j], xor | xorMasks[j],
195                    andMasks[i], xorMasks[i]))
196             continue next_i;
197         }
198         newCount++;
199     }
200     if (newCount == 0)
201         return new ModifierMatcher(and, xor);
202     int[] ands = new int[newCount];
203     int[] xors = new int[newCount];
204     int index = 0;
205     next_i:
206     for (int i=0; i < newCount; i++) {
207         if (implies(and, xor, andMasks[i], xorMasks[i]))
208         continue next_i;
209
210         for (int j=0; j < andMasks.length; j++) {
211         if (j != i
212             && implies(and | andMasks[j], xor | xorMasks[j],
213                    andMasks[i], xorMasks[i]))
214             continue next_i;
215         }
216
217         ands[index] = andMasks[i] | and;
218         xors[index] = xorMasks[i] | xor;
219         index++;
220     }
221     return new ModifierMatcher(ands, xors);
222     }
223
224     private ModifierMatcher or(int and, int xor) {
225     int matchIndex = -1;
226     if (this == denyAll)
227         return new ModifierMatcher(and, xor);
228     for (int i=0; i< andMasks.length; i++) {
229         if (implies(and, xor, andMasks[i], xorMasks[i]))
230         return this;
231         if (implies(andMasks[i], xorMasks[i], and, xor)) {
232         matchIndex = i;
233         break;
234         }
235     }
236     int[] ands, xors;
237     if (matchIndex == -1) {
238         matchIndex = andMasks.length;
239         ands = new int[matchIndex+1];
240         xors = new int[matchIndex+1];
241         System.arraycopy(andMasks, 0, ands, 0, matchIndex);
242         System.arraycopy(xorMasks, 0, xors, 0, matchIndex);
243     } else {
244         ands = (int[]) andMasks.clone();
245         xors = (int[]) xorMasks.clone();
246     }
247     ands[matchIndex] = and;
248     xors[matchIndex] = xor;
249     return new ModifierMatcher(ands, xors);
250     }
251
252     /**
253      * Creates a new ModifierMatcher, that matches only modifiers, we
254      * also match and also forces the access rights, to be accessModif
255      * (or less restrictive).
256      * @param accessModif the access modifier. Use 0 for package access,
257      * or Modifier.PRIVATE/PROTECTED/PUBLIC.
258      * @param andAbove allow to be less restrictive.
259      * @return a new modifier matcher that will also use the given accesses.
260      */

261     public ModifierMatcher forceAccess(int accessModif, boolean andAbove) {
262     if (andAbove) {
263         if (accessModif == Modifier.PRIVATE)
264         return this;
265         if (accessModif == 0)
266         return this.and(Modifier.PRIVATE, 0);
267
268         ModifierMatcher result = this.and(Modifier.PUBLIC, PUBLIC);
269         if (accessModif == Modifier.PROTECTED)
270         return result
271             .or(this.and(Modifier.PROTECTED, Modifier.PROTECTED));
272         if (accessModif == Modifier.PUBLIC)
273         return result;
274         throw new IllegalArgumentException JavaDoc(""+accessModif);
275     } else {
276         if (accessModif == 0)
277         return this.and(Modifier.PRIVATE |
278                 Modifier.PROTECTED | Modifier.PUBLIC, 0);
279         else
280         return this.and(accessModif, accessModif);
281     }
282     }
283
284     public ModifierMatcher forbidAccess(int accessModif, boolean andAbove) {
285     if (andAbove) {
286         if (accessModif == Modifier.PRIVATE)
287         // This forbids all access.
288
return denyAll;
289         if (accessModif == 0)
290         return this.and(Modifier.PRIVATE, Modifier.PRIVATE);
291         if (accessModif == Modifier.PROTECTED)
292         return this.and(Modifier.PROTECTED | Modifier.PUBLIC, 0);
293         if (accessModif == Modifier.PUBLIC)
294         return this.and(Modifier.PUBLIC, 0);
295         throw new IllegalArgumentException JavaDoc(""+accessModif);
296     } else {
297         if (accessModif == 0) {
298         return this.and(Modifier.PRIVATE, Modifier.PRIVATE)
299             .or(this.and(Modifier.PROTECTED, Modifier.PROTECTED))
300             .or(this.and(Modifier.PUBLIC, Modifier.PUBLIC));
301         } else
302         return this.and(accessModif, 0);
303     }
304     }
305
306     public final ModifierMatcher forceModifier(int modifier) {
307     return this.and(modifier, modifier);
308     }
309
310     public final ModifierMatcher forbidModifier(int modifier) {
311     return this.and(modifier, 0);
312     }
313
314     public final boolean matches(int modifiers) {
315     for (int i=0; i< andMasks.length; i++)
316         if ((modifiers & andMasks[i]) == xorMasks[i])
317         return true;
318
319     return false;
320     }
321
322     public final boolean matches(Identifier ident) {
323     int modifiers;
324     /* XXX NEW INTERFACE OR ANOTHER METHOD IN IDENTIFIER? */
325     if (ident instanceof ClassIdentifier)
326         modifiers = ((ClassIdentifier) ident).getModifiers();
327     else if (ident instanceof MethodIdentifier)
328         modifiers = ((MethodIdentifier) ident).getModifiers();
329     else if (ident instanceof FieldIdentifier)
330         modifiers = ((FieldIdentifier) ident).getModifiers();
331     else
332         return false;
333     return matches(modifiers);
334     }
335
336     public final boolean matchesSub(Identifier ident, String JavaDoc name) {
337     return true;
338     }
339
340     public final String JavaDoc getNextComponent(Identifier ident) {
341     return null;
342     }
343
344     public Object JavaDoc clone() {
345     try {
346         return super.clone();
347     } catch (CloneNotSupportedException JavaDoc ex) {
348         throw new IncompatibleClassChangeError JavaDoc(getClass().getName());
349     }
350     }
351 }
352
Popular Tags