1 25 package net.sf.javaguard; 26 27 import java.io.*; 28 import java.util.*; 29 30 31 35 public class ScriptFile implements ScriptConstants { 36 37 private Vector entries; 38 39 40 private String name; 41 42 43 44 45 49 public ScriptFile(File aScript) 50 throws IOException { 51 entries = new Vector(); 52 setName(aScript.getName()); 53 54 InputStream is = null; 55 try { 56 is = new FileInputStream(aScript); 57 StreamTokenizer tk = new StreamTokenizer(new BufferedReader(new InputStreamReader(is))); 58 tk.resetSyntax(); 60 tk.eolIsSignificant(true); 61 tk.whitespaceChars(0x00, 0x20); 63 tk.wordChars('!', '~'); 65 tk.slashSlashComments(true); 67 tk.slashStarComments(true); 68 tk.commentChar('#'); 69 readEntries(tk); 70 } finally { 71 if (null != is) { 72 is.close(); 73 } 74 } 75 } 76 77 78 82 private void readEntries(StreamTokenizer tk) 83 throws IOException { 84 ScriptEntry scriptEntry; 85 try { 86 while ( null != (scriptEntry = readNextEntry(tk))) { 87 entries.add(scriptEntry); 88 } 89 } catch (IOException ex) { 90 IOException ioex = new IOException("Parse error at line " + tk.lineno() 91 + ": " + ex.getMessage() + "."); 92 ioex.fillInStackTrace(); 93 throw ioex; 94 } catch (IllegalArgumentException iaex) { 95 IOException ioex = new IOException("Parse error at line " + tk.lineno() 96 + ": " + iaex.getMessage() + "."); 97 ioex.fillInStackTrace(); 98 throw ioex; 99 } 100 } 101 102 103 109 private ScriptEntry readNextEntry(StreamTokenizer tk) 110 throws IOException, IllegalArgumentException { 111 ScriptEntry entry = null; 113 114 readNextToken(tk); 116 if (tk.ttype == StreamTokenizer.TT_EOF) return null; 117 118 int type = parseDirective(tk); 120 if (type < 0) { 121 throw new IllegalArgumentException ("Unknown script file directive"); 122 } 123 124 readNextTokenInLine(tk); 126 entry = new ScriptEntry(type, tk.sval); 127 128 switch (type) { 130 case TYPE_ATTRIBUTE: 131 if (!Tools.isInArrayIgnoreCase(entry.getName(), validAttrs)) { 132 throw new IllegalArgumentException ("Unknown attribute option specified"); 133 } 134 if (conditionalReadNextTokenInLine(tk)) { 136 entry.setInfo(tk.sval); 137 } 138 break; 139 140 case TYPE_RENAME: 141 if (!Tools.isInArrayIgnoreCase(entry.getName(), renameAttrs)) { 142 throw new IllegalArgumentException ("Unknown rename option specified"); 143 } 144 if (conditionalReadNextTokenInLine(tk)) { 146 entry.setInfo(tk.sval); 147 } 148 break; 149 150 case TYPE_PRESERVE: 151 if (!Tools.isInArrayIgnoreCase(entry.getName(), preserveAttrs)) { 152 throw new IllegalArgumentException ("Unknown preserve option specified"); 153 } 154 if (conditionalReadNextTokenInLine(tk)) { 155 entry.setInfo(tk.sval); 156 } 157 break; 158 159 case TYPE_PACKAGE: 160 readClassOptions(tk, entry); 162 break; 163 164 case TYPE_PACKAGE_MAP: 165 readNextTokenInLine(tk); 167 checkJavaIdentifier(tk.sval); 168 entry.setMappedName(tk.sval); 169 readClassOptions(tk, entry); 171 break; 172 173 case TYPE_CLASS: 174 readClassOptions(tk, entry); 176 break; 177 178 case TYPE_CLASS_MAP: 179 readNextTokenInLine(tk); 181 checkJavaInnerIdentifier(tk.sval); 182 entry.setMappedName(tk.sval); 183 readClassOptions(tk, entry); 184 break; 185 186 case TYPE_METHOD: 187 if (conditionalReadNextTokenInLine(tk)) { 189 checkMethodDescriptor(tk.sval); 190 entry.setDescriptor(tk.sval); 191 } 192 break; 193 194 case TYPE_METHOD_MAP: 195 readNextTokenInLine(tk); 197 checkMethodDescriptor(tk.sval); 198 entry.setDescriptor(tk.sval); 199 readNextTokenInLine(tk); 201 checkJavaIdentifier(tk.sval); 202 entry.setMappedName(tk.sval); 203 break; 204 205 case TYPE_FIELD: 206 if (conditionalReadNextTokenInLine(tk)) { 208 checkJavaType(tk.sval); 209 entry.setDescriptor(tk.sval); 210 } 211 break; 212 213 case TYPE_FIELD_MAP: { 214 readNextTokenInLine(tk); 218 String tmp = tk.sval; 219 if (conditionalReadNextTokenInLine(tk)) { 220 checkJavaType(tmp); 222 entry.setDescriptor(tmp); 223 entry.setMappedName(tk.sval); 224 } else { 225 entry.setMappedName(tmp); 226 } 227 checkJavaIdentifier(entry.getMappedName()); 228 break; 229 } 230 231 case TYPE_IGNORE_METHOD: 232 if (conditionalReadNextTokenInLine(tk)) { 234 checkMethodDescriptor(tk.sval); 235 entry.setDescriptor(tk.sval); 236 } 237 break; 238 239 case TYPE_IGNORE_FIELD: 240 if (conditionalReadNextTokenInLine(tk)) { 242 checkJavaType(tk.sval); 243 entry.setDescriptor(tk.sval); 244 } 245 break; 246 247 case TYPE_OBFUSCATE_METHOD: 248 if (conditionalReadNextTokenInLine(tk)) { 250 checkMethodDescriptor(tk.sval); 251 entry.setDescriptor(tk.sval); 252 } 253 break; 254 255 256 case TYPE_OBFUSCATE_FIELD: 257 if (conditionalReadNextTokenInLine(tk)) { 259 checkJavaType(tk.sval); 260 entry.setDescriptor(tk.sval); 261 } 262 break; 263 } 264 265 return entry; 266 } 267 268 269 273 private void readNextToken(StreamTokenizer tk) 274 throws IOException { 275 int token = StreamTokenizer.TT_EOL; 276 277 while (token == StreamTokenizer.TT_EOL) { 279 token = tk.nextToken(); 280 } 281 } 282 283 284 288 private void readNextTokenInLine(StreamTokenizer tk) 289 throws IOException { 290 int token = StreamTokenizer.TT_NUMBER; 291 292 while (token == StreamTokenizer.TT_NUMBER) { 294 token = tk.nextToken(); 295 } 296 if (token != StreamTokenizer.TT_WORD) { 297 throw new IOException("Unexpected end of file at line " + tk.lineno() + " of script file."); 298 } 299 } 300 301 302 308 private boolean conditionalReadNextTokenInLine(StreamTokenizer tk) 309 throws IOException { 310 int token = StreamTokenizer.TT_NUMBER; 311 312 while (token == StreamTokenizer.TT_NUMBER) { 314 token = tk.nextToken(); 315 } 316 if (token != StreamTokenizer.TT_WORD) { 318 tk.pushBack(); 319 return false; 320 } 321 return true; 322 } 323 324 325 333 private void readClassOptions(StreamTokenizer tk, ScriptEntry entry) 334 throws IOException, IllegalArgumentException { 335 while (conditionalReadNextTokenInLine(tk)) { 336 int subtype; 337 switch (subtype = parseToken(tk.sval, options, optionTypes)) { 338 case OPTION_TYPE_PUBLIC: 339 entry.setRetainPublic(true); 340 break; 341 342 case OPTION_TYPE_PROTECTED: 343 entry.setRetainProtected(true); 344 break; 345 346 case OPTION_TYPE_METHOD: 347 entry.setRetainMethods(true); 348 break; 349 350 case OPTION_TYPE_FIELD: 351 entry.setRetainFields(true); 352 break; 353 354 default: 355 throw new IllegalArgumentException ("Unknown class option"); 356 } 357 } 358 if ( (entry.canRetainFields() || entry.canRetainMethods()) && 361 !entry.canRetainPublic() && !entry.canRetainProtected()) { 362 throw new IllegalArgumentException ("Missing option \"public\" or \"protected\""); 363 } 364 if ( (entry.canRetainPublic() || entry.canRetainProtected()) && 367 !entry.canRetainFields() && !entry.canRetainMethods()) { 368 entry.setRetainFields(true); 371 entry.setRetainMethods(true); 372 } 373 } 374 375 376 381 private int parseDirective(StreamTokenizer tk) { 382 if (tk.ttype == StreamTokenizer.TT_WORD) { 383 return parseToken(tk.sval, directives, directiveTypes); 384 } 385 return -1; 386 } 387 388 389 398 private int parseToken(String str, String [] list, int[] codes) { 399 for (int i=0; i<list.length; i++) { 400 if (str.equalsIgnoreCase(list[i])) { 401 return codes[i]; 402 } 403 } 404 return -1; 405 } 406 407 408 409 410 414 private void checkMethodDescriptor(String s) 415 throws IllegalArgumentException { 416 if (s.length() == 0 || s.charAt(0) != '(') { 417 throw new IllegalArgumentException ("Empty or invalid method descriptor."); 418 } 419 s = s.substring(1); 420 421 while (s.length() > 0 && s.charAt(0) != ')') { 423 s = checkFirstJavaType(s); 424 } 425 checkJavaType(s.substring(1)); 426 } 427 428 429 434 private String checkFirstJavaType(String s) 435 throws IllegalArgumentException { 436 while (s.charAt(0) == '[') { 438 s = s.substring(1); 439 if (s.length() == 0) { 440 throw new IllegalArgumentException ("Invalid Java type"); 441 } 442 } 443 444 int pos = 0; 446 switch (s.charAt(0)) { 447 case 'B': 448 case 'C': 449 case 'D': 450 case 'F': 451 case 'I': 452 case 'J': 453 case 'S': 454 case 'V': 455 case 'Z': 456 break; 457 458 case 'L': 459 pos = s.indexOf(';'); 460 if (pos == -1) { 461 throw new IllegalArgumentException ("Invalid class or interface type specification"); 462 } 463 checkClassSpec(s.substring(0, pos)); 465 break; 466 467 default: 468 throw new IllegalArgumentException ("Unknown Java type"); 469 } 470 return s.substring(pos + 1); 471 } 472 473 474 475 479 private void checkJavaType(String s) 480 throws IllegalArgumentException { 481 if (!checkFirstJavaType(s).equals("")) { 482 throw new IllegalArgumentException ("Invalid Java type"); 483 } 484 } 485 486 487 488 489 493 private void checkClassSpec(String s) 494 throws IllegalArgumentException { 495 if (s.length() == 0) { 496 throw new IllegalArgumentException ("Class specification may not be empty"); 497 } 498 499 int pos = -1; 500 while ((pos = s.lastIndexOf('$')) != -1) { 502 checkJavaInnerIdentifier(s.substring(pos + 1)); 503 s = s.substring(0, pos); 504 } 505 while ((pos = s.lastIndexOf('/')) != -1) { 507 checkJavaIdentifier(s.substring(pos + 1)); 508 s = s.substring(0, pos); 509 } 510 checkJavaIdentifier(s); 511 } 512 513 514 518 private void checkJavaIdentifier(String s) 519 throws IllegalArgumentException { 520 if (s.length() == 0 || !Character.isJavaIdentifierStart(s.charAt(0))) { 521 throw new IllegalArgumentException ("Identifier empty or invalid start character"); 522 } 523 for (int i = 1; i < s.length(); i++) { 524 if (!Character.isJavaIdentifierPart(s.charAt(i))) { 525 throw new IllegalArgumentException ("Invalid character inside the identifier"); 526 } 527 } 528 } 529 530 531 536 private void checkJavaInnerIdentifier(String s) 537 throws IllegalArgumentException { 538 if (s.length() == 0) { 539 throw new IllegalArgumentException ("Identifier may not be empty"); 540 } 541 for (int i = 0; i < s.length(); i++) { 542 if (!Character.isJavaIdentifierPart(s.charAt(i))) { 543 throw new IllegalArgumentException ("Invalid character inside the identifier"); 544 } 545 } 546 } 547 548 549 550 551 555 public Iterator iterator() { 556 return entries.iterator(); 557 } 558 559 560 561 562 566 public void setName(String aName) { 567 this.name = aName; 568 } 569 570 571 575 public String getName() { 576 return name; 577 } 578 } 579 | Popular Tags |