1 19 20 package org.netbeans.modules.java.source.parsing; 21 22 23 import java.io.ByteArrayInputStream ; 24 import java.io.ByteArrayOutputStream ; 25 import java.io.File ; 26 import java.io.FileInputStream ; 27 import java.io.FileOutputStream ; 28 import java.io.IOException ; 29 import java.io.InputStream ; 30 import java.io.InputStreamReader ; 31 import java.io.OutputStream ; 32 import java.io.OutputStreamWriter ; 33 import java.io.Reader ; 34 import java.io.Writer ; 35 import java.net.MalformedURLException ; 36 import java.net.URI ; 37 import java.net.URL ; 38 import java.nio.CharBuffer ; 39 import java.util.Comparator ; 40 import java.util.zip.ZipEntry ; 41 import java.util.zip.ZipFile ; 42 import javax.lang.model.element.Modifier; 43 import javax.lang.model.element.NestingKind; 44 import javax.tools.JavaFileObject; 45 import org.netbeans.modules.java.ClassDataLoader; 46 import org.netbeans.modules.java.JavaDataLoader; 47 import org.netbeans.modules.java.preprocessorbridge.spi.JavaFileFilterImplementation; 48 import org.openide.filesystems.FileObject; 49 import org.openide.filesystems.FileUtil; 50 import org.openide.filesystems.FileUtil; 51 import org.openide.util.NbBundle; 52 import org.openide.util.Utilities; 53 54 60 public class FileObjects { 61 62 public static final Comparator <String > SIMPLE_NAME_STRING_COMPARATOR = new SimpleNameStringComparator(); 63 public static final Comparator <JavaFileObject> SIMPLE_NAME_FILEOBJECT_COMPARATOR = new SimpleNameFileObjectComparator(); 64 65 66 public static final String JAVA = JavaDataLoader.JAVA_EXTENSION; 67 public static final String CLASS = ClassDataLoader.CLASS_EXTENSION; 68 public static final String JAR = "jar"; public static final String ZIP = "zip"; public static final String HTML = "html"; public static final String SIG = "sig"; public static final String RS = "rs"; 74 75 76 private FileObjects() { 77 } 78 79 81 82 83 89 public static JavaFileObject zipFileObject( File zipFile, String folder, String baseName, long mtime) { 90 assert zipFile != null; 91 return new ZipFileObject( zipFile, folder, baseName, mtime); 92 } 93 94 public static JavaFileObject zipFileObject(ZipFile zipFile, String folder, String baseName, long mtime) { 95 assert zipFile != null; 96 return new CachedZipFileObject (zipFile, folder, baseName, mtime); 97 } 98 99 105 public static JavaFileObject fileFileObject( final File file, final File root, final JavaFileFilterImplementation filter) { 106 assert file != null; 107 assert root != null; 108 String [] pkgNamePair = getFolderAndBaseName(getRelativePath(root,file),File.separatorChar); 109 return new RegularFileObject( file, convertFolder2Package(pkgNamePair[0], File.separatorChar), pkgNamePair[1], filter); 110 } 111 112 120 public static JavaFileObject nbFileObject (final FileObject file) throws IOException { 121 return nbFileObject (file, null, false); 122 } 123 124 133 public static JavaFileObject nbFileObject (final FileObject file, JavaFileFilterImplementation filter, boolean renderNow) throws IOException { 134 assert file != null; 135 if (!file.isValid() || file.isVirtual()) { 136 throw new InvalidFileException (file); 137 } 138 return new SourceFileObject (file, filter, renderNow); 139 } 140 141 149 public static JavaFileObject memoryFileObject( CharSequence content, CharSequence name ) { 150 final String nameStr = name.toString(); 151 if (!nameStr.equals(getBaseName(nameStr))) { 152 throw new IllegalArgumentException ("Memory is flat"); } 154 int length = content.length(); 155 if ( length != 0 && Character.isWhitespace( content.charAt( length - 1 ) ) ) { 156 return new MemoryFileObject( nameStr, CharBuffer.wrap( content ) ); 157 } 158 else { 159 return new MemoryFileObject( nameStr, (CharBuffer )CharBuffer.allocate( length + 1 ).append( content ).append( ' ' ).flip() ); 160 } 161 162 } 163 164 public static String stripExtension( String fileName ) { 165 int dot = fileName.lastIndexOf("."); 166 return (dot == -1 ? fileName : fileName.substring(0, dot)); 167 } 168 169 170 174 public static String getName (final JavaFileObject fo, final boolean noExt) { 175 assert fo != null; 176 if (fo instanceof Base) { 177 Base baseFileObject = (Base) fo; 178 if (noExt) { 179 return baseFileObject.getName(); 180 } 181 else { 182 StringBuilder sb = new StringBuilder (); 183 sb.append (baseFileObject.getName()); 184 sb.append('.'); sb.append(baseFileObject.getExt()); 186 return sb.toString(); 187 } 188 } 189 try { 190 final URL url = fo.toUri().toURL(); 191 String path = url.getPath(); 192 int index1 = path.lastIndexOf('/'); 193 int len; 194 if (noExt) { 195 final int index2 = path.lastIndexOf('.'); 196 if (index2>index1) { 197 len = index2; 198 } 199 else { 200 len = path.length(); 201 } 202 } 203 else { 204 len = path.length(); 205 } 206 path = path.substring(index1+1,len); 207 return path; 208 } catch (MalformedURLException e) { 209 return null; 210 } 211 } 212 213 214 220 public static String getBaseName( String fileName ) { 221 return getBaseName(fileName, File.separatorChar); 222 } 223 224 231 public static String getBaseName( String fileName, char separator ) { 232 return getFolderAndBaseName(fileName, separator)[1]; 233 } 234 235 236 242 public static String [] getFolderAndBaseName (final String fileName, final char separator) { 243 final int i = fileName.lastIndexOf( separator ); 244 if ( i == -1 ) { 245 return new String [] {"",fileName}; } 247 else { 248 return new String [] { 249 fileName.substring(0,i), 250 fileName.substring( i + 1 ) 251 }; 252 } 253 } 254 255 public static String getBinaryName (final File file, final File root) { 256 assert file != null && root != null; 257 String fileName = FileObjects.getRelativePath (root, file); 258 int index = fileName.lastIndexOf('.'); if (index > 0) { 260 fileName = fileName.substring(0,index); 261 } 262 return fileName.replace(File.separatorChar,'.'); } 264 265 public static String getSimpleName( JavaFileObject fo ) { 266 267 String name = getName(fo,true); 268 int i = name.lastIndexOf( '$' ); 269 if ( i == -1 ) { 270 return name; 271 } 272 else { 273 return name.substring( i + 1 ); 274 } 275 } 276 277 public static String getSimpleName( String fileName ) { 278 279 String name = getBaseName( fileName ); 280 281 int i = name.lastIndexOf( '$' ); 282 if ( i == -1 ) { 283 return name; 284 } 285 else { 286 return name.substring( i + 1 ); 287 } 288 289 } 290 291 public static String convertPackage2Folder( String packageName ) { 292 return packageName.replace( '.', '/' ); 293 } 294 295 296 public static String convertFolder2Package (String packageName) { 297 return convertFolder2Package (packageName, '/'); } 299 300 public static String convertFolder2Package( String packageName, char folderSeparator ) { 301 return packageName.replace( folderSeparator, '.' ); 302 } 303 304 305 public static String getRelativePath (final String packageName, final String relativeName) { 306 StringBuilder relativePath = new StringBuilder (); 307 relativePath.append(packageName.replace('.','/')); 308 relativePath.append(relativeName); 309 return relativePath.toString(); 310 } 311 312 public static String [] getParentRelativePathAndName (final String className) { 313 if (className.charAt(className.length()-1) == '.') { 314 return null; 315 } 316 final int index = className.lastIndexOf('.'); 317 if (index<0) { 318 return new String [] { 319 "", className 321 }; 322 } 323 else { 324 return new String [] { 325 className.substring(0,index).replace('.','/'), className.substring(index+1) 327 }; 328 } 329 } 330 331 332 334 336 public static abstract class Base implements JavaFileObject { 337 338 protected final JavaFileObject.Kind kind; 339 protected final String pkgName; 340 protected final String nameWithoutExt; 341 protected final String ext; 342 343 protected Base (final String pkgName, final String name) { 344 assert pkgName != null; 345 assert name != null; 346 this.pkgName = pkgName; 347 String [] res = getNameExtPair(name); 348 this.nameWithoutExt = res[0]; 349 this.ext = res[1]; 350 if (FileObjects.JAVA.equalsIgnoreCase(ext)) { this.kind = Kind.SOURCE; 352 } 353 else if (FileObjects.CLASS.equalsIgnoreCase(ext) || "sig".equals(ext)) { this.kind = Kind.CLASS; 355 } 356 else if (FileObjects.HTML.equalsIgnoreCase(ext)) { this.kind = Kind.HTML; 358 } 359 else { 360 this.kind = Kind.OTHER; 361 } 362 } 363 364 public JavaFileObject.Kind getKind() { 365 return this.kind; 366 } 367 368 public boolean isNameCompatible (String simplename, JavaFileObject.Kind k) { 369 if (this.kind != k) { 370 return false; 371 } 372 return nameWithoutExt.equals(simplename); 373 } 374 375 public NestingKind getNestingKind() { 376 return null; 377 } 378 379 public Modifier getAccessLevel() { 380 return null; 381 } 382 383 @Override 384 public String toString() { 385 return this.toUri().toString(); 386 } 387 388 public String getPackage () { 389 return this.pkgName; 390 } 391 392 public String getNameWithoutExtension () { 393 return this.nameWithoutExt; 394 } 395 396 public String getName () { 397 return this.nameWithoutExt + '.' + ext; 398 } 399 400 public String getExt () { 401 return this.ext; 402 } 403 404 private static String [] getNameExtPair (String name) { 405 int index = name.lastIndexOf ('.'); 406 String namenx; 407 String ext; 408 if (index <= 0) { 409 namenx =name; 410 ext = ""; } 412 else { 413 namenx = name.substring(0,index); 414 if (index == name.length()-1) { 415 ext = ""; 416 } 417 else { 418 ext = name.substring(index+1); 419 } 420 } 421 return new String [] { 422 namenx, 423 ext 424 }; 425 } 426 } 427 428 public static abstract class FileBase extends Base { 429 430 protected final File f; 431 432 protected FileBase (final File file, final String pkgName, final String name) { 433 super (pkgName, name); 434 assert file != null; 435 assert file.equals(FileUtil.normalizeFile(file)); 436 this.f = file; 437 } 438 439 public File getFile () { 440 return this.f; 441 } 442 } 443 444 445 public static class InvalidFileException extends IOException { 446 447 public InvalidFileException () { 448 super (); 449 } 450 451 public InvalidFileException (final FileObject fo) { 452 super (NbBundle.getMessage(FileObjects.class,"FMT_InvalidFile",FileUtil.getFileDisplayName(fo))); 453 } 454 } 455 456 457 public static String getRelativePath (final File root, final File fo) { 458 final String rootPath = root.getAbsolutePath(); 459 final String foPath = fo.getAbsolutePath(); 460 assert foPath.startsWith(rootPath); 461 int index = rootPath.length(); 462 if (rootPath.charAt(index-1)!=File.separatorChar) { 463 index++; 464 } 465 int foIndex = foPath.length(); 466 if (foIndex <= index) { 467 return ""; } 469 return foPath.substring(index); 470 } 471 472 private static class RegularFileObject extends FileBase { 473 474 private URI uriCache; 475 private final JavaFileFilterImplementation filter; 476 477 public RegularFileObject(final File f, final String packageName, final String baseName, final JavaFileFilterImplementation filter) { 478 super (f, packageName, baseName); 479 this.filter = filter; 480 } 481 482 public InputStream openInputStream() throws IOException { 483 return new FileInputStream (f); 484 } 485 486 public Reader openReader (boolean b) throws IOException { 487 throw new UnsupportedOperationException (); 488 } 489 490 public OutputStream openOutputStream() throws IOException { 491 return new FileOutputStream (f); 492 } 493 494 public Writer openWriter() throws IOException { 495 return new OutputStreamWriter (new FileOutputStream (f)); 497 } 498 499 public @Override boolean isNameCompatible(String simplename, JavaFileObject.Kind kind) { 500 boolean res = super.isNameCompatible(simplename, kind); 501 if (res) { 502 return res; 503 } 504 else if (Utilities.isWindows()) { 505 return nameWithoutExt.equalsIgnoreCase(simplename); 506 } 507 else { 508 return false; 509 } 510 } 511 512 public URI toUri () { 513 if (this.uriCache == null) { 514 this.uriCache = f.toURI(); 515 } 516 return this.uriCache; 517 } 518 519 public long getLastModified() { 520 return f.lastModified(); 521 } 522 523 public boolean delete() { 524 return f.delete(); 525 } 526 527 public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { 528 529 char[] result; 530 InputStreamReader in = new InputStreamReader (new FileInputStream (this.f), encodingName); 531 try { 532 int len = (int)this.f.length(); 533 result = new char [len+1]; 534 int red = 0, rv; 535 while ((rv=in.read(result,red,len-red))>0 && (red=red+rv)<len); 536 } finally { 537 in.close(); 538 } 539 result[result.length-1]='\n'; CharSequence buffer = CharBuffer.wrap (result); 541 if (this.filter != null) { 542 buffer = this.filter.filterCharSequence(buffer); 543 } 544 return buffer; 545 } 546 547 @Override 548 public boolean equals(Object other) { 549 if (!(other instanceof RegularFileObject)) 550 return false; 551 RegularFileObject o = (RegularFileObject) other; 552 return f.equals(o.f); 553 } 554 555 @Override 556 public int hashCode() { 557 return f.hashCode(); 558 } 559 560 } 561 562 565 public abstract static class ZipFileBase extends Base { 566 567 protected final long mtime; 568 protected final String resName; 569 570 public ZipFileBase (final String folderName, final String baseName, long mtime) { 571 super (convertFolder2Package(folderName),baseName); 572 this.mtime = mtime; 573 if (folderName.length() == 0) { 574 this.resName = baseName; 575 } 576 else { 577 StringBuilder resName = new StringBuilder (folderName); 578 resName.append('/'); resName.append(baseName); 580 this.resName = resName.toString(); 581 } 582 } 583 584 public OutputStream openOutputStream() throws IOException { 585 throw new UnsupportedOperationException (); 586 } 587 588 public Reader openReader(boolean b) throws IOException { 589 if (this.getKind() == JavaFileObject.Kind.CLASS) { 590 throw new UnsupportedOperationException (); 591 } 592 else { 593 return new InputStreamReader (openInputStream(),FileObjects.encodingName); 594 } 595 } 596 597 public Writer openWriter() throws IOException { 598 throw new UnsupportedOperationException (); 599 } 600 601 public long getLastModified() { 602 return mtime; 603 } 604 605 public boolean delete() { 606 throw new UnsupportedOperationException (); 607 } 608 609 public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException { 610 Reader r = openReader(ignoreEncodingErrors); 611 try { 612 int red = 0, rv; 613 614 int len = (int)this.getSize(); 615 char[] result = new char [len+1]; 616 while ((rv=r.read(result,red,len-red))>0 && (red=red+rv)<len); 617 618 int j=0; 619 for (int i=0; i<red;i++) { 620 if (result[i] =='\r') { if (i+1>=red || result[i+1]!='\n') { result[j++] = '\n'; } 624 } 625 else { 626 result[j++] = result[i]; 627 } 628 } 629 result[j]='\n'; return CharBuffer.wrap (result,0,j); 631 } finally { 632 r.close(); 633 } 634 } 635 636 public final URI toUri () { 637 URI zdirURI = this.getArchiveURI(); 638 return URI.create ("jar:"+zdirURI.toString()+"!/"+resName); } 640 641 @Override 642 public int hashCode() { 643 return this.resName.hashCode(); 644 } 645 646 @Override 647 public boolean equals(Object other) { 648 if (!(other instanceof ZipFileBase)) 649 return false; 650 ZipFileBase o = (ZipFileBase) other; 651 return getArchiveURI().equals(o.getArchiveURI()) && resName.equals(o.resName); 652 } 653 654 protected abstract URI getArchiveURI (); 655 656 protected abstract long getSize() throws IOException ; 657 658 } 659 660 private static class ZipFileObject extends ZipFileBase { 661 662 663 665 private final File archiveFile; 666 667 668 ZipFileObject(final File archiveFile, final String folderName, final String baseName, long mtime) { 669 super (folderName,baseName,mtime); 670 assert archiveFile != null : "archiveFile == null"; this.archiveFile = archiveFile; 672 673 } 674 675 public InputStream openInputStream() throws IOException { 676 class ZipInputStream extends InputStream { 677 678 private ZipFile zipfile; 679 private InputStream delegate; 680 681 public ZipInputStream (ZipFile zf) throws IOException { 682 this.zipfile = zf; 683 this.delegate = zf.getInputStream(new ZipEntry (resName)); 684 } 685 686 public int read() throws IOException { 687 throw new java.lang.UnsupportedOperationException ("Not supported yet."); 688 } 689 690 public int read(byte b[], int off, int len) throws IOException { 691 return delegate.read(b, off, len); 692 } 693 694 public int available() throws IOException { 695 return this.delegate.available(); 696 } 697 698 public void close() throws IOException { 699 try { 700 this.delegate.close(); 701 } finally { 702 this.zipfile.close(); 703 } 704 } 705 706 707 }; 708 ZipFile zf = new ZipFile (archiveFile); 709 return new ZipInputStream (zf); 710 } 711 712 public URI getArchiveURI () { 713 return this.archiveFile.toURI(); 714 } 715 716 protected long getSize () throws IOException { 717 ZipFile zf = new ZipFile (archiveFile); 718 try { 719 ZipEntry ze = zf.getEntry(this.resName); 720 return ze == null ? 0L : ze.getSize(); 721 } finally { 722 zf.close(); 723 } 724 } 725 } 726 727 private static class CachedZipFileObject extends ZipFileBase { 728 729 private ZipFile zipFile; 730 731 CachedZipFileObject(final ZipFile zipFile, final String folderName, final String baseName, long mtime) { 732 super (folderName,baseName,mtime); 733 assert zipFile != null : "archiveFile == null"; this.zipFile = zipFile; 735 } 736 737 public InputStream openInputStream() throws IOException { 738 return this.zipFile.getInputStream(new ZipEntry (this.resName)); 739 } 740 741 public URI getArchiveURI () { 742 return new File (this.zipFile.getName()).toURI(); 743 } 744 745 protected long getSize() throws IOException { 746 ZipEntry ze = this.zipFile.getEntry(this.resName); 747 return ze == null ? 0L : ze.getSize(); 748 } 749 } 750 751 752 754 private static class MemoryFileObject extends Base { 755 756 private String fileName; 757 private CharBuffer cb; 758 759 public MemoryFileObject( String fileName, CharBuffer cb ) { 760 super ("",fileName); this.cb = cb; 762 this.fileName = fileName; 763 } 764 765 766 772 public java.nio.CharBuffer getCharContent(boolean ignoreEncodingErrors) throws java.io.IOException { 773 return cb; 774 } 775 776 public boolean delete() { 777 return false; 779 } 780 781 public URI toUri () { 782 return URI.create (this.nameWithoutExt); 783 } 784 785 public long getLastModified() { 786 return System.currentTimeMillis(); } 788 789 795 public InputStream openInputStream() throws java.io.IOException { 796 return new ByteArrayInputStream (cb.toString().getBytes("UTF-8")); 797 } 798 799 805 public java.io.OutputStream openOutputStream() throws java.io.IOException { 806 throw new UnsupportedOperationException (); 807 } 808 809 816 public java.io.Reader openReader (boolean b) throws java.io.IOException { 817 throw new UnsupportedOperationException (); 818 } 819 820 825 public java.io.Writer openWriter() throws java.io.IOException { 826 throw new UnsupportedOperationException (); 827 } 828 829 } 830 831 private static class SimpleNameStringComparator implements Comparator <String > { 832 833 public int compare( String o1, String o2 ) { 834 return getSimpleName( o1 ).compareTo( getSimpleName( o2 ) ); 835 } 836 837 } 838 839 private static class SimpleNameFileObjectComparator implements Comparator <JavaFileObject> { 840 841 public int compare( JavaFileObject o1, JavaFileObject o2 ) { 842 843 String n1 = getSimpleName( o1 ); 844 String n2 = getSimpleName( o2 ); 845 846 return n1.compareTo( n2 ); 847 } 848 849 } 850 851 static final String encodingName = new OutputStreamWriter (new ByteArrayOutputStream ()).getEncoding(); 852 853 } 854 | Popular Tags |