1 /* 2 * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 /* 26 * Portions Copyright (c) 2011 Jonas Maebe 27 */ 28 29 30 package fpc.tools.javapp; 31 32 import java.util.*; 33 import java.io.*; 34 import java.util.jar.*; 35 36 37 /** 38 * Strores flag values according to command line options 39 * and sets path where to find classes. 40 * 41 * @author Sucheta Dambalkar 42 */ 43 public class JavapEnvironment { 44 45 //Access flags 46 public static final int PRIVATE = 0; 47 public static final int PROTECTED = 1; 48 public static final int PACKAGE = 2; 49 public static final int PUBLIC = 3; 50 51 //search path flags. 52 private static final int start = 0; 53 private static final int cmdboot= 1; 54 private static final int sunboot = 2; 55 private static final int javaclass= 3; 56 private static final int cmdextdir= 4; 57 private static final int javaext= 5; 58 private static final int cmdclasspath= 6; 59 private static final int envclasspath= 7; 60 private static final int javaclasspath= 8; 61 private static final int currentdir = 9; 62 63 64 // JavapEnvironment flag settings 65 boolean showLineAndLocal = false; 66 int showAccess = PACKAGE; 67 boolean showVerbose = false; 68 String classPathString = null; 69 String bootClassPathString = null; 70 String extDirsString = null; 71 boolean extDirflag; 72 boolean nothingToDo = true; 73 boolean showallAttr = false; 74 boolean generateInclude = false; 75 String classpath = null; 76 String outputName = "java"; 77 ArrayList<String> excludePrefixes; 78 ArrayList<String> skelPrefixes; 79 String prefix_constant = ""; 80 String prefix_field = "f"; 81 String prefix_innerclass = "Inner"; 82 boolean addVarOverloads = false; 83 JavapEnvironment()84 public JavapEnvironment() { 85 excludePrefixes = new ArrayList<String>(); 86 skelPrefixes = new ArrayList<String>(); 87 } 88 89 /** 90 * According to which flags are set, 91 * returns file input stream for classfile to disassemble. 92 */ 93 getFileInputStream(String Name)94 public InputStream getFileInputStream(String Name){ 95 InputStream fileInStream = null; 96 int searchpath = cmdboot; 97 extDirflag = false; 98 try{ 99 if(searchpath == cmdboot){ 100 if(bootClassPathString != null){ 101 //search in specified bootclasspath. 102 classpath = bootClassPathString; 103 if((fileInStream = resolvefilename(Name)) != null) return fileInStream; 104 //no classes found in search path. 105 else searchpath = cmdextdir; 106 } 107 else searchpath = sunboot; 108 } 109 110 if(searchpath == sunboot){ 111 if(System.getProperty("sun.boot.class.path") != null){ 112 //search in sun.boot.class.path 113 classpath = System.getProperty("sun.boot.class.path"); 114 if((fileInStream = resolvefilename(Name)) != null) return fileInStream; 115 //no classes found in search path 116 else searchpath = cmdextdir; 117 } 118 else searchpath = javaclass; 119 } 120 121 if(searchpath == javaclass){ 122 if(System.getProperty("java.class.path") != null){ 123 //search in java.class.path 124 classpath =System.getProperty("java.class.path"); 125 if((fileInStream = resolvefilename(Name)) != null) return fileInStream; 126 //no classes found in search path 127 else searchpath = cmdextdir; 128 } 129 else searchpath = cmdextdir; 130 } 131 132 if(searchpath == cmdextdir){ 133 if(extDirsString != null){ 134 //search in specified extdir. 135 classpath = extDirsString; 136 extDirflag = true; 137 if((fileInStream = resolvefilename(Name)) != null) return fileInStream; 138 //no classes found in search path 139 else { 140 searchpath = cmdclasspath; 141 extDirflag = false; 142 } 143 } 144 else searchpath = javaext; 145 } 146 147 if(searchpath == javaext){ 148 if(System.getProperty("java.ext.dirs") != null){ 149 //search in java.ext.dirs 150 classpath = System.getProperty("java.ext.dirs"); 151 extDirflag = true; 152 if((fileInStream = resolvefilename(Name)) != null) return fileInStream; 153 //no classes found in search path 154 else { 155 searchpath = cmdclasspath; 156 extDirflag = false; 157 } 158 } 159 else searchpath = cmdclasspath; 160 } 161 if(searchpath == cmdclasspath){ 162 if(classPathString != null){ 163 //search in specified classpath. 164 classpath = classPathString; 165 if((fileInStream = resolvefilename(Name)) != null) return fileInStream; 166 //no classes found in search path 167 else searchpath = 8; 168 } 169 else searchpath = envclasspath; 170 } 171 172 if(searchpath == envclasspath){ 173 if(System.getProperty("env.class.path")!= null){ 174 //search in env.class.path 175 classpath = System.getProperty("env.class.path"); 176 if((fileInStream = resolvefilename(Name)) != null) return fileInStream; 177 //no classes found in search path. 178 else searchpath = javaclasspath; 179 } 180 else searchpath = javaclasspath; 181 } 182 183 if(searchpath == javaclasspath){ 184 if(("application.home") == null){ 185 //search in java.class.path 186 classpath = System.getProperty("java.class.path"); 187 if((fileInStream = resolvefilename(Name)) != null) return fileInStream; 188 //no classes found in search path. 189 else searchpath = currentdir; 190 } 191 else searchpath = currentdir; 192 } 193 194 if(searchpath == currentdir){ 195 classpath = "."; 196 //search in current dir. 197 if((fileInStream = resolvefilename(Name)) != null) return fileInStream; 198 else { 199 //no classes found in search path. 200 error("Could not find "+ Name); 201 System.exit(1); 202 } 203 } 204 }catch(SecurityException excsec){ 205 excsec.printStackTrace(); 206 error("fatal exception"); 207 }catch(NullPointerException excnull){ 208 excnull.printStackTrace(); 209 error("fatal exception"); 210 }catch(IllegalArgumentException excill){ 211 excill.printStackTrace(); 212 error("fatal exception"); 213 } 214 215 return null; 216 } 217 218 error(String msg)219 public void error(String msg) { 220 System.err.println("ERROR:" +msg); 221 } 222 223 /** 224 * Resolves file name for classfile to disassemble. 225 */ resolvefilename(String name)226 public InputStream resolvefilename(String name){ 227 String classname = name.replace('.', '/') + ".class"; 228 while (true) { 229 InputStream instream = extDirflag 230 ? resolveExdirFilename(classname) 231 : resolveclasspath(classname); 232 if (instream != null) 233 return instream; 234 int lastindex = classname.lastIndexOf('/'); 235 if (lastindex == -1) return null; 236 classname = classname.substring(0, lastindex) + "$" + 237 classname.substring(lastindex + 1); 238 } 239 } 240 241 /** 242 * Resolves file name for classfile to disassemble if flag exdir is set. 243 */ resolveExdirFilename(String classname)244 public InputStream resolveExdirFilename(String classname){ 245 if(classpath.indexOf(File.pathSeparator) != -1){ 246 //separates path 247 StringTokenizer st = new StringTokenizer(classpath, File.pathSeparator); 248 while(st.hasMoreTokens()){ 249 String path = st.nextToken(); 250 InputStream in = resolveExdirFilenamehelper(path, classname); 251 if (in != null) 252 return in; 253 } 254 }else return (resolveExdirFilenamehelper(classpath, classname)); 255 256 return null; 257 } 258 259 /** 260 * Resolves file name for classfile to disassemble. 261 */ resolveclasspath(String classname)262 public InputStream resolveclasspath(String classname){ 263 if(classpath.indexOf(File.pathSeparator) != -1){ 264 StringTokenizer st = new StringTokenizer(classpath, File.pathSeparator); 265 //separates path. 266 while(st.hasMoreTokens()){ 267 String path = (st.nextToken()).trim(); 268 InputStream in = resolveclasspathhelper(path, classname); 269 if(in != null) return in; 270 271 } 272 return null; 273 } 274 else return (resolveclasspathhelper(classpath, classname)); 275 } 276 277 278 /** 279 * Returns file input stream for classfile to disassemble if exdir is set. 280 */ resolveExdirFilenamehelper(String path, String classname)281 public InputStream resolveExdirFilenamehelper(String path, String classname){ 282 File fileobj = new File(path); 283 if(fileobj.isDirectory()){ 284 // gets list of files in that directory. 285 File[] filelist = fileobj.listFiles(); 286 for(int i = 0; i < filelist.length; i++){ 287 try{ 288 //file is a jar file. 289 if(filelist[i].toString().endsWith(".jar")){ 290 JarFile jfile = new JarFile(filelist[i]); 291 if((jfile.getEntry(classname)) != null){ 292 293 InputStream filein = jfile.getInputStream(jfile.getEntry(classname)); 294 int bytearraysize = filein.available(); 295 byte []b = new byte[bytearraysize]; 296 int totalread = 0; 297 while(totalread < bytearraysize){ 298 totalread += filein.read(b, totalread, bytearraysize-totalread); 299 } 300 InputStream inbyte = new ByteArrayInputStream(b); 301 filein.close(); 302 return inbyte; 303 } 304 } else { 305 //not a jar file. 306 String filename = path+"/"+ classname; 307 File file = new File(filename); 308 if(file.isFile()){ 309 return (new FileInputStream(file)); 310 } 311 } 312 }catch(FileNotFoundException fnexce){ 313 fnexce.printStackTrace(); 314 error("cant read file"); 315 error("fatal exception"); 316 }catch(IOException ioexc){ 317 ioexc.printStackTrace(); 318 error("fatal exception"); 319 } 320 } 321 } 322 323 return null; 324 } 325 326 327 /** 328 * Returns file input stream for classfile to disassemble. 329 */ resolveclasspathhelper(String path, String classname)330 public InputStream resolveclasspathhelper(String path, String classname){ 331 File fileobj = new File(path); 332 try{ 333 if(fileobj.isDirectory()){ 334 //is a directory. 335 String filename = path+"/"+ classname; 336 File file = new File(filename); 337 if(file.isFile()){ 338 return (new FileInputStream(file)); 339 } 340 341 }else if(fileobj.isFile()){ 342 if(fileobj.toString().endsWith(".jar")){ 343 //is a jar file. 344 JarFile jfile = new JarFile(fileobj); 345 if((jfile.getEntry(classname)) != null){ 346 InputStream filein = jfile.getInputStream(jfile.getEntry(classname)); 347 int bytearraysize = filein.available(); 348 byte []b = new byte[bytearraysize]; 349 int totalread = 0; 350 while(totalread < bytearraysize){ 351 totalread += filein.read(b, totalread, bytearraysize-totalread); 352 } 353 InputStream inbyte = new ByteArrayInputStream(b); 354 filein.close(); 355 return inbyte; 356 } 357 } 358 } 359 }catch(FileNotFoundException fnexce){ 360 fnexce.printStackTrace(); 361 error("cant read file"); 362 error("fatal exception"); 363 }catch(IOException ioexce){ 364 ioexce.printStackTrace(); 365 error("fatal exception"); 366 } 367 return null; 368 } 369 370 371 getJarEntries(String jarname)372 protected SortedSet<String> getJarEntries(String jarname) { 373 SortedSet<String> res = new TreeSet<String>(); 374 375 try{ 376 JarFile jfile = new JarFile(jarname); 377 Enumeration<JarEntry> entries = jfile.entries(); 378 while (entries.hasMoreElements()) { 379 JarEntry entry = entries.nextElement(); 380 String name = entry.getName(); 381 int classpos = name.lastIndexOf(".class"); 382 if ((classpos != -1) && 383 !PascalClassData.isInnerClass(name.substring(0, classpos)) && 384 !entry.isDirectory()) { 385 res.add(name.substring(0, classpos)); 386 } 387 } 388 }catch(FileNotFoundException fnexce){ 389 // fnexce.printStackTrace(); 390 // error("cant read file"); 391 // error("fatal exception"); 392 }catch(IOException ioexc){ 393 // ioexc.printStackTrace(); 394 // error("fatal exception"); 395 } 396 return res; 397 } 398 399 getDirEntries(File fileobj, boolean includeJarEntries)400 protected SortedSet<String> getDirEntries(File fileobj, boolean includeJarEntries) { 401 SortedSet<String> res = new TreeSet<String>(); 402 403 File[] filelist = fileobj.listFiles(); 404 for(int i = 0; i < filelist.length; i++){ 405 //file is a jar file. 406 String fname = filelist[i].toString(); 407 if(includeJarEntries && 408 fname.endsWith(".jar")){ 409 res.addAll(getJarEntries(fname)); 410 } 411 else if (fname.endsWith(".class")) { 412 int classpos = fname.lastIndexOf(".class"); 413 if (classpos != -1) 414 fname = fname.substring(0, classpos); 415 if (!PascalClassData.isInnerClass(fname)) 416 res.add(fname); 417 } 418 } 419 return res; 420 } 421 422 /** 423 * Returns list of non-nested classes found in a path 424 */ getExdirEntries(String path)425 public SortedSet<String> getExdirEntries(String path){ 426 File fileobj = new File(path); 427 if(fileobj.isDirectory()){ 428 return getDirEntries(fileobj,true); 429 } 430 return new TreeSet<String>(); 431 } 432 433 434 /** 435 * Returns list of non-nested classes found in class path 436 */ getClasspathEntries(String path)437 public SortedSet<String> getClasspathEntries(String path){ 438 File fileobj = new File(path); 439 if(fileobj.isDirectory()){ 440 return getDirEntries(fileobj, false); 441 442 }else if(fileobj.toString().endsWith(".jar")){ 443 return getJarEntries(fileobj.toString()); 444 } 445 return new TreeSet<String>(); 446 } 447 448 449 /** 450 * Return a list of all non-nested classes in the currently set exdir classpath 451 */ getAllExdirEntries()452 public SortedSet<String> getAllExdirEntries(){ 453 SortedSet<String> res; 454 if(classpath.indexOf(File.pathSeparator) != -1){ 455 res = new TreeSet<String>(); 456 //separates path 457 StringTokenizer st = new StringTokenizer(classpath, File.pathSeparator); 458 while(st.hasMoreTokens()){ 459 String path = st.nextToken(); 460 res.addAll(getExdirEntries(path)); 461 } 462 }else res = getExdirEntries(classpath); 463 464 return res; 465 } 466 467 /** 468 * Return a list of all non-nested classes in the currently set classpath 469 */ getAllClasspathEntries()470 public SortedSet<String> getAllClasspathEntries(){ 471 SortedSet<String> res; 472 if(classpath.indexOf(File.pathSeparator) != -1){ 473 res = new TreeSet<String>(); 474 StringTokenizer st = new StringTokenizer(classpath, File.pathSeparator); 475 //separates path. 476 while(st.hasMoreTokens()){ 477 String path = (st.nextToken()).trim(); 478 res.addAll(getClasspathEntries(path)); 479 } 480 } 481 else res = getClasspathEntries(classpath); 482 return res; 483 } 484 485 getAllEntries()486 public SortedSet<String> getAllEntries(){ 487 if (extDirflag) 488 return getAllExdirEntries(); 489 else 490 return getAllClasspathEntries(); 491 } 492 493 getClassesList()494 public SortedSet<String> getClassesList(){ 495 SortedSet<String> res = new TreeSet<String>(); 496 int searchpath = cmdboot; 497 extDirflag = false; 498 try{ 499 if(searchpath == cmdboot){ 500 if(bootClassPathString != null){ 501 //search in specified bootclasspath. 502 classpath = bootClassPathString; 503 res.addAll(getAllEntries()); 504 searchpath = cmdextdir; 505 } 506 else searchpath = sunboot; 507 } 508 509 if(searchpath == sunboot){ 510 if(System.getProperty("sun.boot.class.path") != null){ 511 //search in sun.boot.class.path 512 classpath = System.getProperty("sun.boot.class.path"); 513 res.addAll(getAllEntries()); 514 searchpath = cmdextdir; 515 } 516 else searchpath = javaclass; 517 } 518 519 if(searchpath == javaclass){ 520 if(System.getProperty("java.class.path") != null){ 521 //search in java.class.path 522 classpath =System.getProperty("java.class.path"); 523 res.addAll(getAllEntries()); 524 searchpath = cmdextdir; 525 } 526 else searchpath = cmdextdir; 527 } 528 529 if(searchpath == cmdextdir){ 530 if(extDirsString != null){ 531 //search in specified extdir. 532 classpath = extDirsString; 533 extDirflag = true; 534 res.addAll(getAllEntries()); 535 searchpath = cmdclasspath; 536 extDirflag = false; 537 } 538 else searchpath = javaext; 539 } 540 541 if(searchpath == javaext){ 542 if(System.getProperty("java.ext.dirs") != null){ 543 //search in java.ext.dirs 544 classpath = System.getProperty("java.ext.dirs"); 545 extDirflag = true; 546 res.addAll(getAllEntries()); 547 searchpath = cmdclasspath; 548 extDirflag = false; 549 } 550 else searchpath = cmdclasspath; 551 } 552 if(searchpath == cmdclasspath){ 553 if(classPathString != null){ 554 //search in specified classpath. 555 classpath = classPathString; 556 res.addAll(getAllEntries()); 557 searchpath = 8; 558 } 559 else searchpath = envclasspath; 560 } 561 562 if(searchpath == envclasspath){ 563 if(System.getProperty("env.class.path")!= null){ 564 //search in env.class.path 565 classpath = System.getProperty("env.class.path"); 566 res.addAll(getAllEntries()); 567 searchpath = javaclasspath; 568 } 569 else searchpath = javaclasspath; 570 } 571 572 if(searchpath == javaclasspath){ 573 if(("application.home") == null){ 574 //search in java.class.path 575 classpath = System.getProperty("java.class.path"); 576 res.addAll(getAllEntries()); 577 searchpath = currentdir; 578 } 579 else searchpath = currentdir; 580 } 581 582 if(searchpath == currentdir){ 583 classpath = "."; 584 //search in current dir. 585 res.addAll(getAllEntries()); 586 } 587 }catch(SecurityException excsec){ 588 excsec.printStackTrace(); 589 error("fatal exception"); 590 }catch(NullPointerException excnull){ 591 excnull.printStackTrace(); 592 error("fatal exception"); 593 }catch(IllegalArgumentException excill){ 594 excill.printStackTrace(); 595 error("fatal exception"); 596 } 597 598 return res; 599 } 600 601 602 603 604 } 605