001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the file COPYING. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * If you do not have access to this file, you may request a copy from * 011 * help@hdfgroup.org. * 012 ****************************************************************************/ 013 014package hdf.view; 015 016import java.io.BufferedInputStream; 017import java.io.BufferedOutputStream; 018import java.io.File; 019import java.io.FileInputStream; 020import java.io.FileOutputStream; 021import java.io.RandomAccessFile; 022import java.util.Enumeration; 023import java.util.Hashtable; 024import java.util.StringTokenizer; 025 026import javax.swing.filechooser.FileFilter; 027 028/** 029 * A convenience implementation of FileFilter that filters out all files except 030 * for those type extensions that it knows about. 031 * 032 * @author Peter X. Cao 033 * @version 2.4 9/6/2007 034 */ 035public class DefaultFileFilter extends FileFilter { 036 private static FileFilter FILE_FILTER_HDF = null; 037 private static FileFilter FILE_FILTER_HDF4 = null; 038 private static FileFilter FILE_FILTER_HDF5 = null; 039 private static FileFilter FILE_FILTER_JPEG = null; 040 private static FileFilter FILE_FILTER_TIFF = null; 041 private static FileFilter FILE_FILTER_PNG = null; 042 private static FileFilter FILE_FILTER_GIF = null; 043 private static FileFilter FILE_FILTER_BMP = null; 044 private static FileFilter FILE_FILTER_IMG = null; 045 private static FileFilter FILE_FILTER_TEXT = null; 046 private static FileFilter FILE_FILTER_BINARY = null; 047 048 private Hashtable<String, DefaultFileFilter> filters = null; 049 private String description = null; 050 private String fullDescription = null; 051 private boolean useExtensionsInDescription = true; 052 053 /** 054 * Creates a file filter. If no filters are added, then all files are 055 * accepted. 056 * 057 * @see #addExtension 058 */ 059 public DefaultFileFilter() { 060 this.filters = new Hashtable<String, DefaultFileFilter>(); 061 } 062 063 /** 064 * Creates a file filter that accepts files with the given extension. 065 * Example: new DefaultFileFilter("jpg"); 066 * 067 * @see #addExtension 068 * 069 * @param extension the file extension to filter on 070 */ 071 public DefaultFileFilter(String extension) { 072 this(extension, null); 073 } 074 075 /** 076 * Creates a file filter that accepts the given file type. Example: new 077 * DefaultFileFilter("jpg", "JPEG Image Images"); 078 * 079 * Note that the "." before the extension is not needed. If provided, it 080 * will be ignored. 081 * 082 * @see #addExtension 083 * 084 * @param extension the file extension to filter on 085 * @param description the file extension full description 086 */ 087 public DefaultFileFilter(String extension, String description) { 088 this(); 089 if (extension != null) { 090 addExtension(extension); 091 } 092 if (description != null) { 093 setDescription(description); 094 } 095 } 096 097 /** 098 * Creates a file filter from the given string array. Example: new 099 * DefaultFileFilter(String {"gif", "jpg"}); 100 * 101 * Note that the "." before the extension is not needed and will be ignored. 102 * 103 * @see #addExtension 104 * 105 * @param filters 106 * the list of filter names 107 */ 108 public DefaultFileFilter(String[] filters) { 109 this(filters, null); 110 } 111 112 /** 113 * Creates a file filter from the given string array and description. 114 * Example: new DefaultFileFilter(String {"gif", "jpg"}, 115 * "Gif and JPG Images"); 116 * 117 * Note that the "." before the extension is not needed and will be ignored. 118 * 119 * @see #addExtension 120 * 121 * @param filters 122 * the list of filter names 123 * @param description 124 * the name of the filter list 125 */ 126 public DefaultFileFilter(String[] filters, String description) { 127 this(); 128 for (int i = 0; i < filters.length; i++) { 129 // add filters one by one 130 addExtension(filters[i]); 131 } 132 if (description != null) { 133 setDescription(description); 134 } 135 } 136 137 /** 138 * Return true if this file should be shown in the directory pane, false if 139 * it shouldn't. 140 * 141 * Files that begin with "." are ignored. 142 * 143 * @see #getExtension 144 */ 145 @Override 146 public boolean accept(File f) { 147 if (f != null) { 148 if (f.isDirectory()) { 149 return true; 150 } 151 String extension = getExtension(f); 152 if ((extension != null) && (filters.get(getExtension(f)) != null)) { 153 return true; 154 } 155 } 156 157 return false; 158 } 159 160 /** 161 * Return the extension portion of the file's name. 162 * 163 * @param f The file to get the extension portion of the name for 164 * 165 * @return The extension portion of the given file's name 166 * 167 * @see #getExtension 168 * @see FileFilter#accept 169 */ 170 public String getExtension(File f) { 171 if (f != null) { 172 String filename = f.getName(); 173 int i = filename.lastIndexOf('.'); 174 if ((i > 0) && (i < filename.length() - 1)) { 175 return filename.substring(i + 1).toLowerCase(); 176 } 177 } 178 return null; 179 } 180 181 /** 182 * Adds a filetype "dot" extension to filter against. 183 * 184 * For example: the following code will create a filter that filters out all 185 * files except those that end in ".jpg" and ".tif": 186 * 187 * DefaultFileFilter filter = new DefaultFileFilter(); 188 * filter.addExtension("jpg"); filter.addExtension("tif"); or 189 * filter.addExtension("jpg, tif"); 190 * 191 * Note that the "." before the extension is not needed and will be ignored. 192 * 193 * @param extension the file extension to add to the file filter 194 */ 195 public void addExtension(String extension) { 196 if (filters == null) { 197 filters = new Hashtable<String, DefaultFileFilter>(5); 198 } 199 200 String ext = null; 201 StringTokenizer st = new StringTokenizer(extension, ","); 202 while (st.hasMoreElements()) { 203 ext = st.nextToken().trim(); 204 filters.put(ext.toLowerCase(), this); 205 } 206 fullDescription = null; 207 } 208 209 /** 210 * @return the human readable description of this filter. For example: 211 * "JPEG and GIF Image Files (*.jpg, *.gif)" 212 */ 213 @Override 214 public String getDescription() { 215 if (fullDescription == null) { 216 if ((description == null) || isExtensionListInDescription()) { 217 fullDescription = description == null ? "(" : description 218 + " ("; 219 // build the description from the extension list 220 Enumeration<String> extensions = filters.keys(); 221 if (extensions != null) { 222 223 if (!extensions.hasMoreElements()) { 224 fullDescription = null; 225 return null; 226 } 227 228 fullDescription += "." + extensions.nextElement(); 229 while (extensions.hasMoreElements()) { 230 fullDescription += ", " 231 + extensions.nextElement(); 232 } 233 } 234 fullDescription += ")"; 235 } 236 else { 237 fullDescription = description; 238 } 239 } 240 return fullDescription; 241 } 242 243 /** 244 * Sets the human readable description of this filter. For example: 245 * filter.setDescription("Gif and JPG Images"); 246 * 247 * @param description the full description of the file filter 248 */ 249 public void setDescription(String description) { 250 this.description = description; 251 fullDescription = null; 252 } 253 254 /** 255 * Determines whether the extension list (.jpg, .gif, etc) should show up in 256 * the human readable description. 257 * 258 * Only relevent if a description was provided in the constructor or using 259 * setDescription(); 260 * 261 * @param b the show state of the extension list 262 */ 263 public void setExtensionListInDescription(boolean b) { 264 useExtensionsInDescription = b; 265 fullDescription = null; 266 } 267 268 /** 269 * @return whether the extension list (.jpg, .gif, etc) should show up in 270 * the human readable description. 271 * 272 * Only relevent if a description was provided in the constructor or using 273 * setDescription(); 274 */ 275 public boolean isExtensionListInDescription() { 276 return useExtensionsInDescription; 277 } 278 279 /** @return a file filter for HDF4/5 file. */ 280 public static FileFilter getFileFilter() { 281 // update extension 282 String fileExtension = ViewProperties.getFileExtension(); 283 284 DefaultFileFilter filter = new DefaultFileFilter(); 285 filter.setDescription("HDF & more"); 286 287 filter.addExtension(fileExtension); 288 FILE_FILTER_HDF = filter; 289 290 return filter; 291 } 292 293 /** @return s file filter for HDF4 file. */ 294 public static FileFilter getFileFilterHDF4() { 295 DefaultFileFilter filter = new DefaultFileFilter(); 296 filter.addExtension("hdf"); 297 filter.addExtension("h4"); 298 filter.addExtension("hdf4"); 299 filter.setDescription("HDF4 files"); 300 FILE_FILTER_HDF4 = filter; 301 302 return filter; 303 } 304 305 /**@return a file filter for HDF5 file. */ 306 public static FileFilter getFileFilterHDF5() { 307 DefaultFileFilter filter = new DefaultFileFilter(); 308 filter.addExtension("h5"); 309 filter.addExtension("hdf5"); 310 filter.setDescription("HDF5 files"); 311 FILE_FILTER_HDF5 = filter; 312 313 return filter; 314 } 315 316 /** @return a file filter for JPEG image files. */ 317 public static FileFilter getFileFilterJPEG() { 318 DefaultFileFilter filter = new DefaultFileFilter(); 319 filter.addExtension("jpg"); 320 filter.addExtension("jpeg"); 321 filter.addExtension("jpe"); 322 filter.addExtension("jif"); 323 filter.addExtension("jfif"); 324 filter.addExtension("jfi"); 325 filter.setDescription("JPEG images"); 326 FILE_FILTER_JPEG = filter; 327 328 return filter; 329 } 330 331 /** @return a file filter for TIFF image files. */ 332 public static FileFilter getFileFilterTIFF() { 333 DefaultFileFilter filter = new DefaultFileFilter(); 334 filter.addExtension("tif"); 335 filter.addExtension("tiff"); 336 filter.setDescription("TIFF images"); 337 FILE_FILTER_TIFF = filter; 338 339 return filter; 340 } 341 342 /** @return a file filter for PNG image files. */ 343 public static FileFilter getFileFilterPNG() { 344 DefaultFileFilter filter = new DefaultFileFilter(); 345 filter.addExtension("png"); 346 filter.setDescription("PNG images"); 347 FILE_FILTER_PNG = filter; 348 349 return filter; 350 } 351 352 /** @return a file filter for BMP image files. */ 353 public static FileFilter getFileFilterBMP() { 354 DefaultFileFilter filter = new DefaultFileFilter(); 355 filter.addExtension("bmp"); 356 filter.addExtension("dib"); 357 filter.setDescription("BMP images"); 358 FILE_FILTER_BMP = filter; 359 360 return filter; 361 } 362 363 /** @return a file filter for GIF image files. */ 364 public static FileFilter getFileFilterGIF() { 365 DefaultFileFilter filter = new DefaultFileFilter(); 366 filter.addExtension("gif"); 367 filter.setDescription("GIF images"); 368 FILE_FILTER_GIF = filter; 369 370 return filter; 371 } 372 373 /** @return a file filter for GIF, JPEG, BMP, or PNG image files. */ 374 public static FileFilter getImageFileFilter() { 375 DefaultFileFilter filter = new DefaultFileFilter(); 376 filter.addExtension("jpg"); 377 filter.addExtension("jpeg"); 378 filter.addExtension("jpe"); 379 filter.addExtension("jif"); 380 filter.addExtension("jfif"); 381 filter.addExtension("jfi"); 382 filter.addExtension("png"); 383 filter.addExtension("gif"); 384 filter.addExtension("bmp"); 385 filter.addExtension("dib"); 386 filter.setDescription("GIF, JPEG, BMP, or PNG images"); 387 FILE_FILTER_IMG = filter; 388 389 return filter; 390 } 391 392 /** @return a file filter for text file. */ 393 public static FileFilter getFileFilterText() { 394 DefaultFileFilter filter = new DefaultFileFilter(); 395 filter.addExtension("txt"); 396 filter.addExtension("text"); 397 filter.setDescription("Text"); 398 FILE_FILTER_TEXT = filter; 399 400 return filter; 401 } 402 403 /** @return a file filter for binary file. */ 404 public static FileFilter getFileFilterBinary() { 405 DefaultFileFilter filter = new DefaultFileFilter(); 406 filter.addExtension("bin"); 407 filter.setDescription("Binary"); 408 FILE_FILTER_BINARY = filter; 409 410 return filter; 411 } 412 413 /** 414 * look at the first 4 bytes of the file to see if it is an HDF4 file. 415 * byte[0]=14, byte[1]=3, byte[2]=19, byte[3]=1 or if it is a netCDF file 416 * byte[0]=67, byte[1]=68, byte[2]=70, byte[3]=1 or 417 * 418 * @param filename The name of the file to check 419 * 420 * @return true if the specified file is an HDF4 file; false otherwise 421 */ 422 public static boolean isHDF4(String filename) { 423 boolean ish4 = false; 424 RandomAccessFile raf = null; 425 426 try { 427 raf = new RandomAccessFile(filename, "r"); 428 } 429 catch (Exception ex) { 430 raf = null; 431 } 432 433 if (raf == null) { 434 return false; 435 } 436 437 byte[] header = new byte[4]; 438 try { 439 raf.read(header); 440 } 441 catch (Exception ex) { 442 header = null; 443 } 444 445 if (header != null) { 446 if ( 447 // HDF4 448 ((header[0] == 14) && (header[1] == 3) && (header[2] == 19) && (header[3] == 1)) 449 /* 450 * // netCDF || (header[0]==67 && header[1]==68 && header[2]==70 && 451 * header[3]==1) 452 */ 453 ) { 454 ish4 = true; 455 } 456 else { 457 ish4 = false; 458 } 459 } 460 461 try { 462 raf.close(); 463 } 464 catch (Exception ex) { 465 } 466 467 return ish4; 468 } 469 470 /** 471 * look at the first 8 bytes of the file to see if it is an HDF5 file. 472 * byte[0]=-199 which is 137 in unsigned byte, byte[1]=72, byte[2]=68, 473 * byte[3]=70, byte[4]=13, byte[5]=10, byte[6]=26, byte[7]=10 474 * 475 * @param filename The name of the file to check 476 * 477 * @return true if the specified file is an HDF5 file; false otherwise 478 */ 479 public static boolean isHDF5(String filename) { 480 boolean ish5 = false; 481 RandomAccessFile raf = null; 482 483 try { 484 raf = new RandomAccessFile(filename, "r"); 485 } 486 catch (Exception ex) { 487 raf = null; 488 } 489 490 if (raf == null) { 491 return false; 492 } 493 494 byte[] header = new byte[8]; 495 long fileSize = 0; 496 try { 497 fileSize = raf.length(); 498 } 499 catch (Exception ex) { 500 } 501 502 // The super block is located by searching for the HDF5 file signature 503 // at byte offset 0, byte offset 512 and at successive locations in the 504 // file, each a multiple of two of the previous location, i.e. 0, 512, 505 // 1024, 2048, etc 506 long offset = 0; 507 while (!ish5 && (offset < fileSize)) { 508 try { 509 raf.seek(offset); 510 raf.read(header); 511 } 512 catch (Exception ex) { 513 header = null; 514 } 515 516 if ((header[0] == -119) && (header[1] == 72) && (header[2] == 68) 517 && (header[3] == 70) && (header[4] == 13) 518 && (header[5] == 10) && (header[6] == 26) 519 && (header[7] == 10)) { 520 ish5 = true; 521 } 522 else { 523 ish5 = false; 524 if (offset == 0) { 525 offset = 512; 526 } 527 else { 528 offset *= 2; 529 } 530 } 531 } 532 533 try { 534 raf.close(); 535 } 536 catch (Exception ex) { 537 } 538 539 return ish5; 540 } 541 542 /** 543 * look at the first 4 bytes of the file to see if it is a netCDF file 544 * byte[0]=67, byte[1]=68, byte[2]=70, byte[3]=1 or 545 * 546 * @param filename The name of the file to check 547 * 548 * @return true if the specified file is a NetCDF file; false otherwise 549 */ 550 public static boolean isNetcdf(String filename) { 551 boolean isnc = false; 552 RandomAccessFile raf = null; 553 554 try { 555 raf = new RandomAccessFile(filename, "r"); 556 } 557 catch (Exception ex) { 558 raf = null; 559 } 560 561 if (raf == null) { 562 return false; 563 } 564 565 byte[] header = new byte[4]; 566 try { 567 raf.read(header); 568 } 569 catch (Exception ex) { 570 header = null; 571 } 572 573 if (header != null) { 574 if ( 575 // netCDF 576 (header[0] == 67) && (header[1] == 68) && (header[2] == 70) 577 && (header[3] == 1)) { 578 isnc = true; 579 } 580 else { 581 isnc = false; 582 } 583 } 584 585 try { 586 raf.close(); 587 } 588 catch (Exception ex) { 589 } 590 591 return isnc; 592 } 593 594 /** 595 * Read HDF5 user block data into byte array. 596 * 597 * @param filename The name of the file to read the HDF5 user block from 598 * 599 * @return a byte array of user block, or null if there is user data. 600 */ 601 public static byte[] getHDF5UserBlock(String filename) { 602 byte[] userBlock = null; 603 RandomAccessFile raf = null; 604 605 try { 606 raf = new RandomAccessFile(filename, "r"); 607 } 608 catch (Exception ex) { 609 try { 610 raf.close(); 611 } 612 catch (Throwable err) { 613 ; 614 } 615 raf = null; 616 } 617 618 if (raf == null) { 619 return null; 620 } 621 622 byte[] header = new byte[8]; 623 long fileSize = 0; 624 try { 625 fileSize = raf.length(); 626 } 627 catch (Exception ex) { 628 fileSize = 0; 629 } 630 if (fileSize <= 0) { 631 try { 632 raf.close(); 633 } 634 catch (Throwable err) { 635 ; 636 } 637 return null; 638 } 639 640 // The super block is located by searching for the HDF5 file signature 641 // at byte offset 0, byte offset 512 and at successive locations in the 642 // file, each a multiple of two of the previous location, i.e. 0, 512, 643 // 1024, 2048, etc 644 long offset = 0; 645 boolean ish5 = false; 646 while (offset < fileSize) { 647 try { 648 raf.seek(offset); 649 raf.read(header); 650 } 651 catch (Exception ex) { 652 header = null; 653 } 654 655 if ((header[0] == -119) && (header[1] == 72) && (header[2] == 68) 656 && (header[3] == 70) && (header[4] == 13) 657 && (header[5] == 10) && (header[6] == 26) 658 && (header[7] == 10)) { 659 ish5 = true; 660 break; // find the end of user block 661 } 662 else { 663 ish5 = false; 664 if (offset == 0) { 665 offset = 512; 666 } 667 else { 668 offset *= 2; 669 } 670 } 671 } 672 673 if (!ish5 || (offset == 0)) { 674 try { 675 raf.close(); 676 } 677 catch (Throwable err) { 678 ; 679 } 680 return null; 681 } 682 683 int blockSize = (int) offset; 684 userBlock = new byte[blockSize]; 685 try { 686 raf.seek(0); 687 raf.read(userBlock, 0, blockSize); 688 } 689 catch (Exception ex) { 690 userBlock = null; 691 } 692 693 try { 694 raf.close(); 695 } 696 catch (Exception ex) { 697 } 698 699 return userBlock; 700 } 701 702 /** 703 * Write HDF5 user block data into byte array. 704 * 705 * @param fin The name of the file to copy to the output file 706 * 707 * @param fout The name of the file to write HDF5 user block data to 708 * 709 * @param buf The HDF5 user block data to write into the output file 710 * 711 * @return a byte array of user block, or null if there is user data. 712 */ 713 public static boolean setHDF5UserBlock(String fin, String fout, byte[] buf) { 714 boolean ish5 = false; 715 716 if ((buf == null) || (buf.length <= 0)) { 717 return false; 718 } 719 720 File tmpFile = new File(fin); 721 if (!tmpFile.exists()) { 722 return false; 723 } 724 725 // find the end of user block for the input file; 726 RandomAccessFile raf = null; 727 try { 728 raf = new RandomAccessFile(fin, "r"); 729 } 730 catch (Exception ex) { 731 raf = null; 732 } 733 734 if (raf == null) { 735 return false; 736 } 737 738 byte[] header = new byte[8]; 739 long fileSize = 0; 740 try { 741 fileSize = raf.length(); 742 } 743 catch (Exception ex) { 744 fileSize = 0; 745 } 746 try { 747 fileSize = raf.length(); 748 } 749 catch (Exception ex) { 750 fileSize = 0; 751 } 752 if (fileSize <= 0) { 753 try { 754 raf.close(); 755 } 756 catch (Throwable err) { 757 ; 758 } 759 return false; 760 } 761 762 // The super block is located by searching for the HDF5 file signature 763 // at byte offset 0, byte offset 512 and at successive locations in the 764 // file, each a multiple of two of the previous location, i.e. 0, 512, 765 // 1024, 2048, etc 766 long offset = 0; 767 while (offset < fileSize) { 768 try { 769 raf.seek(offset); 770 raf.read(header); 771 } 772 catch (Exception ex) { 773 header = null; 774 } 775 776 if ((header[0] == -119) && (header[1] == 72) && (header[2] == 68) 777 && (header[3] == 70) && (header[4] == 13) 778 && (header[5] == 10) && (header[6] == 26) 779 && (header[7] == 10)) { 780 ish5 = true; 781 break; 782 } 783 else { 784 ish5 = false; 785 if (offset == 0) { 786 offset = 512; 787 } 788 else { 789 offset *= 2; 790 } 791 } 792 } 793 try { 794 raf.close(); 795 } 796 catch (Throwable err) { 797 ; 798 } 799 800 if (!ish5) { 801 return false; 802 } 803 804 int length = 0; 805 int bsize = 1024; 806 byte[] buffer; 807 BufferedInputStream bi = null; 808 BufferedOutputStream bo = null; 809 810 try { 811 bi = new BufferedInputStream(new FileInputStream(fin)); 812 } 813 catch (Exception ex) { 814 try { 815 bi.close(); 816 } 817 catch (Exception ex2) { 818 } 819 return false; 820 } 821 822 try { 823 bo = new BufferedOutputStream(new FileOutputStream(fout)); 824 } 825 catch (Exception ex) { 826 try { 827 bo.close(); 828 } 829 catch (Exception ex2) { 830 } 831 try { 832 bi.close(); 833 } 834 catch (Exception ex2) { 835 } 836 return false; 837 } 838 839 // skip the header of original file 840 try { 841 bi.skip(offset); 842 } 843 catch (Exception ex) { 844 } 845 846 // write the header into the new file 847 try { 848 bo.write(buf, 0, buf.length); 849 } 850 catch (Exception ex) { 851 } 852 853 // The super block space is allocated by offset 0, 512, 1024, 2048, etc 854 offset = 512; 855 while (offset < buf.length) { 856 offset *= 2; 857 } 858 int padSize = (int) (offset - buf.length); 859 if (padSize > 0) { 860 byte[] padBuf = new byte[padSize]; 861 try { 862 bo.write(padBuf, 0, padSize); 863 } 864 catch (Exception ex) { 865 } 866 } 867 868 // copy the hdf5 file content from input file to the output file 869 buffer = new byte[bsize]; 870 try { 871 length = bi.read(buffer, 0, bsize); 872 } 873 catch (Exception ex) { 874 length = 0; 875 } 876 while (length > 0) { 877 try { 878 bo.write(buffer, 0, length); 879 length = bi.read(buffer, 0, bsize); 880 } 881 catch (Exception ex) { 882 length = 0; 883 } 884 } 885 886 try { 887 bo.flush(); 888 } 889 catch (Exception ex) { 890 } 891 try { 892 bi.close(); 893 } 894 catch (Exception ex) { 895 } 896 try { 897 bo.close(); 898 } 899 catch (Exception ex) { 900 } 901 return true; 902 } 903}