1 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 ; 29 import java.util.Collection ; 30 import java.util.Iterator ; 31 32 public class ModifierMatcher implements IdentifierMatcher, OptionHandler, Cloneable { 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 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 option, Collection values) { 64 ModifierMatcher mm = this; 65 if (option.equals("access")) { 66 for(Iterator i = values.iterator(); i.hasNext();) { 67 String str = (String ) 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 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 93 ("Unknown access " + str); 94 mm = mm.forceAccess(access, greater); 95 } 96 } 97 } else if (option.equals("modifier")) { 98 for(Iterator i = values.iterator(); i.hasNext();) { 99 String str = (String ) 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 : str.equals("STRICT") ? Modifier.STRICT 113 : 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 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 ("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 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 (""+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 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 (""+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 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 name) { 337 return true; 338 } 339 340 public final String getNextComponent(Identifier ident) { 341 return null; 342 } 343 344 public Object clone() { 345 try { 346 return super.clone(); 347 } catch (CloneNotSupportedException ex) { 348 throw new IncompatibleClassChangeError (getClass().getName()); 349 } 350 } 351 } 352 | Popular Tags |