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 files COPYING and Copyright.html. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * Or, see http://hdfgroup.org/products/hdf-java/doc/Copyright.html. * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.object.h4; 016 017import java.io.File; 018import java.lang.reflect.Array; 019import java.util.Enumeration; 020import java.util.Iterator; 021import java.util.List; 022import java.util.Vector; 023 024import javax.swing.tree.DefaultMutableTreeNode; 025import javax.swing.tree.MutableTreeNode; 026import javax.swing.tree.TreeNode; 027 028import hdf.hdflib.HDFConstants; 029import hdf.hdflib.HDFException; 030import hdf.hdflib.HDFLibrary; 031import hdf.object.Attribute; 032import hdf.object.Dataset; 033import hdf.object.Datatype; 034import hdf.object.FileFormat; 035import hdf.object.Group; 036import hdf.object.HObject; 037 038/** 039 * This class provides file level APIs. File access APIs include retrieving the 040 * file hierarchy, opening and closing file, and writing file content to disk. 041 * 042 * @version 2.4 9/4/2007 043 * @author Peter X. Cao 044 */ 045public class H4File extends FileFormat { 046 /** 047 * 048 */ 049 private static final long serialVersionUID = 8985533001471224030L; 050 051 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H4File.class); 052 053 /** 054 * the file access flag. 055 */ 056 private int flag; 057 058 /** 059 * The root node of the tree structure of this file. 060 */ 061 private DefaultMutableTreeNode rootNode; 062 063 /** 064 * The list of unique (tag, ref) pairs. It is used to avoid duplicate 065 * objects in memory. 066 */ 067 private List objList; 068 069 /** 070 * The GR interface identifier. The identifier is returned by GRstart(fid), 071 * which initializes the GR interface for the file specified by the 072 * parameter. GRstart(fid) is an expensive call. It should be called only 073 * once. Calling GRstart(fid) in a loop should be avoided. 074 */ 075 private int grid; 076 077 private boolean isNetCDF = false; 078 079 /** 080 * The SDS interface identifier. The identifier is returned by 081 * SDstart(fname, flag), which initializes the SD interface for the file 082 * specified by the parameter. SDstart(fname, flag) is an expensive call. It 083 * should be called only once Calling SDstart(fname, flag) in a loop should 084 * be avoided. 085 */ 086 private int sdid; 087 088 /* 089 * secret flag: show CDF0.0, etc., to help debug 090 */ 091 private boolean showAll = false; 092 093 /** 094 * Creates an H4File with read only access. 095 */ 096 public H4File() { 097 this("", WRITE); 098 } 099 100 /** 101 * Creates an H4File with read only access. 102 * 103 * @param pathname 104 * The file path string. 105 */ 106 public H4File(String pathname) { 107 this(pathname, WRITE); 108 } 109 110 /** 111 * Creates an H4File instance with specified file name and access. 112 * <p> 113 * The access parameter values and corresponding behaviors: 114 * <ul> 115 * <li>READ: Read-only access; open() will fail file doesn't exist. 116 * <li>WRITE: Read/Write access; if file doesn't exist, open() will create 117 * it; open() will fail if read/write access not allowed. 118 * <li>CREATE: Read/Write access; create a new file or truncate an existing 119 * one; open() will fail if file can't be created or if file exists but 120 * can't be opened read/write. 121 * </ul> 122 * <p> 123 * This constructor does not open the file for access, nor does it confirm 124 * that the file can later be opened read/write or created. 125 * <p> 126 * The flag returned by {@link #isReadOnly()} is set to true if the access 127 * parameter value is READ, even though the file isn't yet open. 128 * 129 * @param fileName 130 * A valid file name, with a relative or absolute path. 131 * @param access 132 * The file access flag, which determines behavior when file is 133 * opened. Acceptable values are <code> READ, WRITE, </code> and 134 * <code>CREATE</code>. 135 * 136 * @throws NullPointerException 137 * If the <code>fileName</code> argument is <code>null</code>. 138 */ 139 public H4File(String fileName, int access) { 140 super(fileName); 141 isReadOnly = (access == READ); 142 objList = new Vector(); 143 144 this.fid = -1; 145 146 if (access == READ) { 147 flag = HDFConstants.DFACC_READ; 148 } 149 else if (access == WRITE) { 150 flag = HDFConstants.DFACC_WRITE; 151 } 152 else if (access == CREATE) { 153 flag = HDFConstants.DFACC_CREATE; 154 } 155 else { 156 flag = access; 157 } 158 159 String shwAll = System.getProperty("h4showall"); 160 if (shwAll != null) { 161 showAll = true; 162 log.debug("show all is on"); 163 } 164 else { 165 log.debug("show all is off"); 166 } 167 } 168 169 /** 170 * Checks if the given file format is an HDF4 file. 171 * 172 * @param fileformat 173 * the fileformat to be checked. 174 * 175 * @return true if the given file is an HDF4 file; otherwise returns false. 176 */ 177 @Override 178 public boolean isThisType(FileFormat fileformat) { 179 return (fileformat instanceof H4File); 180 } 181 182 /** 183 * Checks if the given file is an HDF4 file or netCDF. HDF4 library supports 184 * netCDF version 2.3.2. It only supports SDS APIs. 185 * 186 * @param filename 187 * the file to be checked. 188 * 189 * @return true if the given file is an HDF4 file; otherwise returns false. 190 */ 191 @Override 192 public boolean isThisType(String filename) { 193 boolean isH4 = false; 194 195 try { 196 isH4 = HDFLibrary.Hishdf(filename); 197 } 198 catch (HDFException ex) { 199 isH4 = false; 200 } 201 202 if (!isH4) { 203 isH4 = isNetCDF(filename); 204 } 205 206 return isH4; 207 } 208 209 /** 210 * Creates an HDF4 file with the specified name and returns a new H4File 211 * instance associated with the file. 212 * 213 * @throws HDFException 214 * If the file cannot be created or if createFlag has unexpected 215 * value. 216 * 217 * @see hdf.object.FileFormat#createFile(java.lang.String, int) 218 * @see #H4File(String, int) 219 */ 220 @Override 221 public FileFormat createFile(String filename, int createFlag) 222 throws Exception { 223 // Flag if we need to create or truncate the file. 224 Boolean doCreateFile = true; 225 226 // Won't create or truncate if CREATE_OPEN specified and file exists 227 if (createFlag == FILE_CREATE_OPEN) { 228 File f = new File(filename); 229 if (f.exists()) { 230 doCreateFile = false; 231 } 232 } 233 234 if (doCreateFile) { 235 int fileid = HDFLibrary.Hopen(filename, HDFConstants.DFACC_CREATE); 236 try { 237 HDFLibrary.Hclose(fileid); 238 } 239 catch (HDFException ex) { 240 log.debug("Hclose failure: ", ex); 241 } 242 } 243 244 return new H4File(filename, WRITE); 245 } 246 247 /** 248 * Creates an H4File instance with specified file name and access. 249 * 250 * @see hdf.object.FileFormat#createInstance(java.lang.String, int) 251 * @see #H4File(String, int) 252 */ 253 @Override 254 public FileFormat createInstance(String filename, int access) 255 throws Exception { 256 return new H4File(filename, access); 257 } 258 259 // Implementing FileFormat 260 @Override 261 public int open() throws Exception { 262 if (fid >= 0) { 263 return fid; // file is opened already 264 } 265 266 log.trace("hdf.H4File - open: begin"); 267 268 // check for valid file access permission 269 if (flag < 0) { // invalid access id 270 throw new HDFException("Invalid access identifer -- " + flag); 271 } 272 else if (flag == HDFConstants.DFACC_READ) { 273 if (!exists()) { 274 throw new HDFException("File does not exist -- " + fullFileName); 275 } 276 else if (exists() && !canRead()) { 277 throw new HDFException("Cannot read file -- " + fullFileName); 278 } 279 } 280 else if ((flag == HDFConstants.DFACC_WRITE) 281 || (flag == HDFConstants.DFACC_CREATE)) { 282 if (exists() && !canWrite()) { 283 throw new HDFException( 284 "Cannot write file, try open as read-only -- " 285 + fullFileName); 286 } 287 } 288 289 // Only check for NetCDF if the file exists, else isNetCDF() throws an exception 290 if (exists()) isNetCDF = isNetCDF(fullFileName); 291 if (isNetCDF) { 292 isReadOnly = true; // read only for netCDF 293 } 294 295 // only support SDS APIs for netCDF 296 if (isNetCDF) { 297 fid = 0; 298 } 299 else { 300 log.trace("HDFLibrary - open({},{})", fullFileName, flag); 301 fid = HDFLibrary.Hopen(fullFileName, flag); 302 log.trace("HDFLibrary - Vstart({})", fid); 303 HDFLibrary.Vstart(fid); 304 grid = HDFLibrary.GRstart(fid); 305 } 306 log.trace("HDFLibrary - SDstart({},{})", fullFileName, flag); 307 sdid = HDFLibrary.SDstart(fullFileName, flag); 308 309 // load the file hierarchy 310 rootNode = loadTree(); 311 312 log.trace("hdf.H4File - open: end"); 313 314 return fid; 315 } 316 317 // Implementing FileFormat 318 @Override 319 public void close() throws HDFException { 320 // clean unused objects 321 if (rootNode != null) { 322 DefaultMutableTreeNode theNode = null; 323 HObject theObj = null; 324 Enumeration local_enum = (rootNode).breadthFirstEnumeration(); 325 while (local_enum.hasMoreElements()) { 326 theNode = (DefaultMutableTreeNode) local_enum.nextElement(); 327 theObj = (HObject) theNode.getUserObject(); 328 if (theObj instanceof Dataset) { 329 ((Dataset) theObj).clearData(); 330 } 331 theObj = null; 332 theNode = null; 333 } 334 } 335 336 try { 337 HDFLibrary.GRend(grid); 338 } 339 catch (HDFException ex) { 340 log.debug("GRend failure: ", ex); 341 } 342 try { 343 HDFLibrary.SDend(sdid); 344 } 345 catch (HDFException ex) { 346 log.debug("SDend failure: ", ex); 347 } 348 try { 349 HDFLibrary.Vend(fid); 350 } 351 catch (HDFException ex) { 352 log.debug("Vend failure: ", ex); 353 } 354 355 HDFLibrary.Hclose(fid); 356 357 fid = -1; 358 objList = null; 359 } 360 361 // Implementing FileFormat 362 @Override 363 public TreeNode getRootNode() { 364 return rootNode; 365 } 366 367 @Override 368 public Group createGroup(String name, Group pgroup) throws Exception { 369 return H4Group.create(name, pgroup); 370 } 371 372 @Override 373 public Datatype createDatatype(int tclass, int tsize, int torder, int tsign) 374 throws Exception { 375 return new H4Datatype(tclass, tsize, torder, tsign); 376 } 377 378 @Override 379 public Datatype createDatatype(int tclass, int tsize, int torder, 380 int tsign, Datatype tbase) throws Exception { 381 return new H4Datatype(tclass, tsize, torder, tsign); 382 } 383 384 @Override 385 public Datatype createDatatype(int tclass, int tsize, int torder, 386 int tsign, String name) throws Exception { 387 throw new UnsupportedOperationException( 388 "HDF4 does not support named datatype."); 389 } 390 391 @Override 392 public Datatype createDatatype(int tclass, int tsize, int torder, 393 int tsign, Datatype tbase, String name) throws Exception { 394 throw new UnsupportedOperationException( 395 "HDF4 does not support named datatype."); 396 } 397 398 @Override 399 public Dataset createScalarDS(String name, Group pgroup, Datatype type, 400 long[] dims, long[] maxdims, long[] chunks, int gzip, 401 Object fillValue, Object data) throws Exception { 402 return H4SDS.create(name, pgroup, type, dims, maxdims, chunks, gzip, 403 fillValue, data); 404 } 405 406 @Override 407 public Dataset createImage(String name, Group pgroup, Datatype type, 408 long[] dims, long[] maxdims, long[] chunks, int gzip, int ncomp, 409 int interlace, Object data) throws Exception { 410 H4GRImage dataset = H4GRImage.create(name, pgroup, type, dims, maxdims, 411 chunks, gzip, ncomp, interlace, data); 412 413 return dataset; 414 } 415 416 /** 417 * Delete an object from the file. 418 * 419 * @param obj 420 * the data object to delete. 421 * 422 * @throws Exception if the object can not be deleted 423 */ 424 @Override 425 public void delete(HObject obj) throws Exception { 426 throw (new UnsupportedOperationException("Cannot delete HDF4 object.")); 427 } 428 429 /** 430 * Copy an object to a group. 431 * 432 * @param srcObj 433 * the object to copy. 434 * @param dstGroup 435 * the destination group. 436 * 437 * @return the destination group, if the copy was successful, or 438 * null otherwise. 439 * 440 * @throws Exception if the object can not be copied 441 */ 442 @Override 443 public TreeNode copy(HObject srcObj, Group dstGroup, String dstName) 444 throws Exception { 445 TreeNode newNode = null; 446 447 log.trace("copy(): start"); 448 if ((srcObj == null) || (dstGroup == null)) { 449 return null; 450 } 451 452 if (dstName == null) { 453 dstName = srcObj.getName(); 454 } 455 log.trace("copy(): dstName={}", dstName); 456 457 if (srcObj instanceof H4SDS) { 458 log.trace("copy(): srcObj instanceof H4SDS"); 459 newNode = new DefaultMutableTreeNode(((H4SDS) srcObj).copy( 460 dstGroup, dstName, null, null)); 461 } 462 else if (srcObj instanceof H4GRImage) { 463 log.trace("copy(): srcObj instanceof H4GRImage"); 464 newNode = new DefaultMutableTreeNode(((H4GRImage) srcObj).copy( 465 dstGroup, dstName, null, null)); 466 } 467 else if (srcObj instanceof H4Vdata) { 468 log.trace("copy(): srcObj instanceof H4Vdata"); 469 newNode = new DefaultMutableTreeNode(((H4Vdata) srcObj).copy( 470 dstGroup, null, null, null)); 471 } 472 else if (srcObj instanceof H4Group) { 473 log.trace("copy(): srcObj instanceof H4Group"); 474 newNode = copyGroup((H4Group) srcObj, (H4Group) dstGroup); 475 } 476 477 log.trace("copy(): finish"); 478 return newNode; 479 } 480 481 /** 482 * Creates a new attribute and attached to the object if attribute does not 483 * exist. Otherwise, just update the value of the attribute. 484 * 485 * @param obj 486 * the object which the attribute is to be attached to. 487 * @param attr 488 * the attribute to attach. 489 * @param isSDglobalAttr 490 * The indicator if the given attribute exists. 491 * 492 * @throws HDFException if the attribute can not be written 493 */ 494 @Override 495 public void writeAttribute(HObject obj, Attribute attr, 496 boolean isSDglobalAttr) throws HDFException { 497 String attrName = attr.getName(); 498 int attrType = attr.getType().toNative(); 499 long[] dims = attr.getDataDims(); 500 int count = 1; 501 if (dims != null) { 502 for (int i = 0; i < dims.length; i++) { 503 count *= (int) dims[i]; 504 } 505 } 506 507 log.trace("writeAttribute(): start count={}", count); 508 Object attrValue = attr.getValue(); 509 if (Array.get(attrValue, 0) instanceof String) { 510 String strValue = (String) Array.get(attrValue, 0); 511 512 if (strValue.length() > count) { 513 // truncate the extra characters 514 strValue = strValue.substring(0, count); 515 Array.set(attrValue, 0, strValue); 516 } 517 else { 518 // pad space to the unused space 519 for (int i = strValue.length(); i < count; i++) { 520 strValue += " "; 521 } 522 } 523 524 byte[] bval = strValue.getBytes(); 525 // add null to the end to get rid of the junks 526 bval[(strValue.length() - 1)] = 0; 527 attrValue = bval; 528 } 529 530 if ((obj instanceof H4Group) && ((H4Group) obj).isRoot()) { 531 if (isSDglobalAttr) { 532 HDFLibrary.SDsetattr(sdid, attrName, attrType, count, attrValue); 533 } 534 else { 535 HDFLibrary.GRsetattr(grid, attrName, attrType, count, attrValue); 536 } 537 return; 538 } 539 540 int id = obj.open(); 541 if (obj instanceof H4Group) { 542 HDFLibrary.Vsetattr(id, attrName, attrType, count, attrValue); 543 } 544 else if (obj instanceof H4SDS) { 545 HDFLibrary.SDsetattr(id, attrName, attrType, count, attrValue); 546 } 547 else if (obj instanceof H4GRImage) { 548 HDFLibrary.GRsetattr(id, attrName, attrType, count, attrValue); 549 } 550 else if (obj instanceof H4Vdata) { 551 HDFLibrary.VSsetattr(id, -1, attrName, attrType, count, attrValue); 552 } 553 obj.close(id); 554 log.trace("writeAttribute(): finish"); 555 } 556 557 private TreeNode copyGroup(H4Group srcGroup, H4Group pgroup) 558 throws Exception { 559 H4Group group = null; 560 int srcgid, dstgid; 561 String gname = null, path = null; 562 563 log.trace("copyGroup(): start"); 564 dstgid = HDFLibrary.Vattach(fid, -1, "w"); 565 if (dstgid < 0) { 566 return null; 567 } 568 569 gname = srcGroup.getName(); 570 srcgid = srcGroup.open(); 571 572 HDFLibrary.Vsetname(dstgid, gname); 573 int ref = HDFLibrary.VQueryref(dstgid); 574 int tag = HDFLibrary.VQuerytag(dstgid); 575 576 if (pgroup.isRoot()) { 577 path = HObject.separator; 578 } 579 else { 580 // add the dataset to the parent group 581 path = pgroup.getPath() + pgroup.getName() + HObject.separator; 582 int pid = pgroup.open(); 583 HDFLibrary.Vinsert(pid, dstgid); 584 pgroup.close(pid); 585 } 586 587 // copy attributes 588 int numberOfAttributes = 0; 589 try { 590 numberOfAttributes = HDFLibrary.Vnattrs(srcgid); 591 } 592 catch (Exception ex) { 593 numberOfAttributes = 0; 594 } 595 596 String[] attrName = new String[1]; 597 byte[] attrBuff = null; 598 int[] attrInfo = new int[3]; // data_type, count, size 599 for (int i = 0; i < numberOfAttributes; i++) { 600 try { 601 attrName[0] = ""; 602 HDFLibrary.Vattrinfo(srcgid, i, attrName, attrInfo); 603 attrBuff = new byte[attrInfo[2]]; 604 HDFLibrary.Vgetattr(srcgid, i, attrBuff); 605 HDFLibrary.Vsetattr(dstgid, attrName[0], attrInfo[0], 606 attrInfo[2], attrBuff); 607 } 608 catch (Exception ex) { 609 continue; 610 } 611 } 612 613 long[] oid = { tag, ref }; 614 group = new H4Group(this, gname, path, pgroup, oid); 615 616 DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(group) { 617 private static final long serialVersionUID = -8601910527549035409L; 618 619 @Override 620 public boolean isLeaf() { 621 return false; 622 } 623 }; 624 pgroup.addToMemberList(group); 625 626 // copy members of the source group to the new group 627 List members = srcGroup.getMemberList(); 628 if ((members != null) && (members.size() > 0)) { 629 Iterator iterator = members.iterator(); 630 while (iterator.hasNext()) { 631 HObject mObj = (HObject) iterator.next(); 632 try { 633 newNode.add((MutableTreeNode) copy(mObj, group)); 634 } 635 catch (Exception ex) { 636 log.debug("newNode.ad failure: ", ex); 637 } 638 } 639 } 640 641 srcGroup.close(srcgid); 642 try { 643 HDFLibrary.Vdetach(dstgid); 644 } 645 catch (Exception ex) { 646 log.debug("Vdetach failure: ", ex); 647 } 648 649 log.trace("copyGroup(): finish"); 650 return newNode; 651 } 652 653 /** 654 * Retrieves and returns the file structure from disk. 655 * <p> 656 * First gets the top level objects or objects that do not belong to any 657 * groups. If a top level object is a group, call the depth_first() to 658 * retrieve the sub-tree of that group, recursively. 659 * 660 */ 661 private DefaultMutableTreeNode loadTree() { 662 if (fid < 0) { 663 return null; 664 } 665 666 long[] oid = { 0, 0 }; 667 int n = 0, ref = -1; 668 int[] argv = null; 669 MutableTreeNode node = null; 670 671 log.trace("loadTree(): start"); 672 H4Group rootGroup = new H4Group(this, "/", null, // root node does not 673 // have a parent 674 // path 675 null, // root node does not have a parent node 676 oid); 677 678 DefaultMutableTreeNode root = new DefaultMutableTreeNode(rootGroup) { 679 private static final long serialVersionUID = 3507473044690724650L; 680 681 @Override 682 public boolean isLeaf() { 683 return false; 684 } 685 }; 686 687 // get top level VGroup 688 int[] tmpN = new int[1]; 689 int[] refs = null; 690 try { 691 // first call to get the number of lone Vgroup 692 n = HDFLibrary.Vlone(fid, tmpN, 0); 693 refs = new int[n]; 694 // second call to get the references of all lone Vgroup 695 n = HDFLibrary.Vlone(fid, refs, n); 696 } 697 catch (HDFException ex) { 698 n = 0; 699 } 700 701 int i0 = Math.max(0, getStartMembers()); 702 int i1 = getMaxMembers(); 703 if (i1 >= n) { 704 i1 = n; 705 i0 = 0; // load all members 706 } 707 i1 += i0; 708 i1 = Math.min(i1, n); 709 710 // Iterate through the file to see members of the group 711 for (int i = i0; i < i1; i++) { 712 ref = refs[i]; 713 H4Group g = getVGroup(HDFConstants.DFTAG_VG, ref, 714 HObject.separator, rootGroup, false); 715 716 if (g != null) { 717 node = new DefaultMutableTreeNode(g) { 718 private static final long serialVersionUID = 8927502967802143369L; 719 720 @Override 721 public boolean isLeaf() { 722 return false; 723 } 724 }; 725 root.add(node); 726 rootGroup.addToMemberList(g); 727 728 // recursively get the sub-tree 729 depth_first(node, null); 730 } 731 } // for (int i=0; i<n; i++) 732 733 // get the top level GR images 734 argv = new int[2]; 735 boolean b = false; 736 try { 737 b = HDFLibrary.GRfileinfo(grid, argv); 738 } 739 catch (HDFException ex) { 740 b = false; 741 } 742 743 if (b) { 744 n = argv[0]; 745 746 for (int i = 0; i < n; i++) { 747 // no duplicate object at top level 748 H4GRImage gr = getGRImage(HDFConstants.DFTAG_RIG, i, 749 HObject.separator, false); 750 if (gr != null) { 751 node = new DefaultMutableTreeNode(gr); 752 root.add(node); 753 rootGroup.addToMemberList(gr); 754 } 755 } // for (int i=0; i<n; i++) 756 } // if ( grid!=HDFConstants.FAIL && HDFLibrary.GRfileinfo(grid,argv) ) 757 758 // get top level SDS 759 try { 760 b = HDFLibrary.SDfileinfo(sdid, argv); 761 } 762 catch (HDFException ex) { 763 b = false; 764 } 765 766 if (b) { 767 n = argv[0]; 768 for (int i = 0; i < n; i++) { 769 // no duplicate object at top level 770 H4SDS sds = getSDS(HDFConstants.DFTAG_NDG, i, 771 HObject.separator, false); 772 if (sds != null) { 773 node = new DefaultMutableTreeNode(sds); 774 root.add(node); 775 rootGroup.addToMemberList(sds); 776 } 777 } // for (int i=0; i<n; i++) 778 } // if (sdid != HDFConstants.FAIL && HDFLibrary.SDfileinfo(sdid, argv)) 779 780 // get top level VData 781 try { 782 n = HDFLibrary.VSlone(fid, tmpN, 0); 783 refs = new int[n]; 784 n = HDFLibrary.VSlone(fid, refs, n); 785 } 786 catch (HDFException ex) { 787 n = 0; 788 } 789 790 for (int i = 0; i < n; i++) { 791 ref = refs[i]; 792 793 // no duplicate object at top level 794 H4Vdata vdata = getVdata(HDFConstants.DFTAG_VS, ref, 795 HObject.separator, false); 796 797 if (vdata != null) { 798 node = new DefaultMutableTreeNode(vdata); 799 root.add(node); 800 rootGroup.addToMemberList(vdata); 801 } 802 } // for (int i=0; i<n; i++) 803 804 if (rootGroup != null) { 805 // retrieve file annotation, GR and SDS globle attributes 806 List attributeList = null; 807 try { 808 attributeList = rootGroup.getMetadata(); 809 } 810 catch (HDFException ex) { 811 log.debug("rootGroup.getMetadata failure: ", ex); 812 } 813 814 if (attributeList != null) { 815 try { 816 getFileAnnotation(fid, attributeList); 817 } 818 catch (HDFException ex) { 819 log.debug("getFileAnnotation failure: ", ex); 820 } 821 try { 822 getGRglobleAttribute(grid, attributeList); 823 } 824 catch (HDFException ex) { 825 log.debug("getGRglobleAttributte failure: ", ex); 826 } 827 try { 828 getSDSglobleAttribute(sdid, attributeList); 829 } 830 catch (HDFException ex) { 831 log.debug("getSDglobleAttributte failure: ", ex); 832 } 833 } 834 } 835 836 log.trace("loadTree(): finish"); 837 return root; 838 } 839 840 /** 841 * Retrieves the tree structure of the file by depth-first order. The 842 * current implementation only retrieves groups and datasets. It does not 843 * include named datatypes and soft links. 844 * 845 * @param parentNode 846 * the parent node. 847 */ 848 private void depth_first(MutableTreeNode parentNode, H4Group pgroup) { 849 if ((pgroup == null) && (parentNode == null)) { 850 return; 851 } 852 853 // System.out.println("H4File.depth_first() pnode = "+parentNode); 854 int nelems = 0, ref = -1, tag = -1, index = -1; 855 int[] tags = null; 856 int[] refs = null; 857 MutableTreeNode node = null; 858 DefaultMutableTreeNode pnode = null; 859 860 if (parentNode != null) { 861 pnode = (DefaultMutableTreeNode) parentNode; 862 pgroup = (H4Group) (pnode.getUserObject()); 863 } 864 865 String fullPath = pgroup.getPath() + pgroup.getName() + HObject.separator; 866 int gid = pgroup.open(); 867 if (gid == HDFConstants.FAIL) { 868 return; 869 } 870 871 try { 872 nelems = HDFLibrary.Vntagrefs(gid); 873 tags = new int[nelems]; 874 refs = new int[nelems]; 875 nelems = HDFLibrary.Vgettagrefs(gid, tags, refs, nelems); 876 } 877 catch (HDFException ex) { 878 nelems = 0; 879 } 880 finally { 881 pgroup.close(gid); 882 } 883 884 int i0 = Math.max(0, getStartMembers()); 885 int i1 = getMaxMembers(); 886 if (i1 >= nelems) { 887 i1 = nelems; 888 i0 = 0; // load all members 889 } 890 i1 += i0; 891 i1 = Math.min(i1, nelems); 892 893 // Iterate through the file to see members of the group 894 for (int i = i0; i < i1; i++) { 895 tag = tags[i]; 896 ref = refs[i]; 897 898 switch (tag) { 899 case HDFConstants.DFTAG_RIG: 900 case HDFConstants.DFTAG_RI: 901 case HDFConstants.DFTAG_RI8: 902 try { 903 index = HDFLibrary.GRreftoindex(grid, (short) ref); 904 } 905 catch (HDFException ex) { 906 index = HDFConstants.FAIL; 907 } 908 if (index != HDFConstants.FAIL) { 909 H4GRImage gr = getGRImage(tag, index, fullPath, true); 910 pgroup.addToMemberList(gr); 911 if ((gr != null) && (pnode != null)) { 912 node = new DefaultMutableTreeNode(gr); 913 pnode.add(node); 914 } 915 } 916 break; 917 case HDFConstants.DFTAG_SD: 918 case HDFConstants.DFTAG_SDG: 919 case HDFConstants.DFTAG_NDG: 920 try { 921 index = HDFLibrary.SDreftoindex(sdid, ref); 922 } 923 catch (HDFException ex) { 924 index = HDFConstants.FAIL; 925 } 926 if (index != HDFConstants.FAIL) { 927 H4SDS sds = getSDS(tag, index, fullPath, true); 928 pgroup.addToMemberList(sds); 929 if ((sds != null) && (pnode != null)) { 930 node = new DefaultMutableTreeNode(sds); 931 pnode.add(node); 932 } 933 } 934 break; 935 case HDFConstants.DFTAG_VH: 936 case HDFConstants.DFTAG_VS: 937 H4Vdata vdata = getVdata(tag, ref, fullPath, true); 938 pgroup.addToMemberList(vdata); 939 if ((vdata != null) && (pnode != null)) { 940 node = new DefaultMutableTreeNode(vdata); 941 pnode.add(node); 942 } 943 break; 944 case HDFConstants.DFTAG_VG: 945 H4Group vgroup = getVGroup(tag, ref, fullPath, pgroup, true); 946 pgroup.addToMemberList(vgroup); 947 if ((vgroup != null) && (pnode != null)) { 948 node = new DefaultMutableTreeNode(vgroup) { 949 private static final long serialVersionUID = -8774836537322039221L; 950 951 @Override 952 public boolean isLeaf() { 953 return false; 954 } 955 }; 956 957 pnode.add(node); 958 959 // check for loops 960 boolean looped = false; 961 DefaultMutableTreeNode theNode = pnode; 962 while ((theNode != null) && !looped) { 963 H4Group theGroup = (H4Group) theNode.getUserObject(); 964 long[] oid = { tag, ref }; 965 if (theGroup.equalsOID(oid)) { 966 looped = true; 967 } 968 else { 969 theNode = (DefaultMutableTreeNode) theNode 970 .getParent(); 971 } 972 } 973 if (!looped) { 974 depth_first(node, null); 975 } 976 } 977 break; 978 default: 979 break; 980 } // switch (tag) 981 982 } // for (int i=0; i<nelms; i++) 983 984 } // private depth_first() 985 986 /** 987 * Retrieve an GR image for the given GR image identifier and index. 988 * 989 * @param index 990 * the index of the image. 991 * @param path 992 * the path of the image. 993 * @param copyAllowed 994 * The indicator if multiple copies of an object is allowed. 995 * 996 * @return the new H5GRImage if successful; otherwise returns null. 997 */ 998 private final H4GRImage getGRImage(int tag, int index, String path, 999 boolean copyAllowed) { 1000 int id = -1, ref = -1; 1001 H4GRImage gr = null; 1002 String[] objName = { "" }; 1003 int[] imgInfo = new int[4]; 1004 int[] dim_sizes = { 0, 0 }; 1005 // int tag = HDFConstants.DFTAG_RIG; 1006 1007 try { 1008 id = HDFLibrary.GRselect(grid, index); 1009 ref = HDFLibrary.GRidtoref(id); 1010 HDFLibrary.GRgetiminfo(id, objName, imgInfo, dim_sizes); 1011 } 1012 catch (HDFException ex) { 1013 id = HDFConstants.FAIL; 1014 } 1015 finally { 1016 try { 1017 HDFLibrary.GRendaccess(id); 1018 } 1019 catch (HDFException ex) { 1020 log.debug("GRendaccess failure: ", ex); 1021 } 1022 } 1023 1024 if (id != HDFConstants.FAIL) { 1025 long oid[] = { tag, ref }; 1026 1027 if (copyAllowed) { 1028 objList.add(oid); 1029 } 1030 else if (find(oid)) { 1031 return null; 1032 } 1033 1034 gr = new H4GRImage(this, objName[0], path, oid); 1035 } 1036 1037 return gr; 1038 } 1039 1040 /** 1041 * Retrieve a SDS for the given sds identifier and index. 1042 * 1043 * @param sdid 1044 * the SDS idendifier. 1045 * @param index 1046 * the index of the SDS. 1047 * @param path 1048 * the path of the SDS. 1049 * @param copyAllowed 1050 * The indicator if multiple copies of an object is allowed. 1051 * 1052 * @return the new H4SDS if successful; otherwise returns null. 1053 */ 1054 private final H4SDS getSDS(int tag, int index, String path, 1055 boolean copyAllowed) { 1056 int id = -1, ref = -1; 1057 H4SDS sds = null; 1058 String[] objName = { "" }; 1059 int[] tmpInfo = new int[HDFConstants.MAX_VAR_DIMS]; 1060 int[] sdInfo = { 0, 0, 0 }; 1061 // int tag = HDFConstants.DFTAG_NDG; 1062 1063 log.trace("getSDS(): start"); 1064 boolean isCoordvar = false; 1065 try { 1066 id = HDFLibrary.SDselect(sdid, index); 1067 if (isNetCDF) { 1068 ref = index; // HDFLibrary.SDidtoref(id) fails for netCDF 1069 tag = H4SDS.DFTAG_NDG_NETCDF; 1070 } 1071 else { 1072 ref = HDFLibrary.SDidtoref(id); 1073 } 1074 HDFLibrary.SDgetinfo(id, objName, tmpInfo, sdInfo); 1075 isCoordvar = HDFLibrary.SDiscoordvar(id); 1076 } 1077 catch (HDFException ex) { 1078 id = HDFConstants.FAIL; 1079 } 1080 finally { 1081 try { 1082 HDFLibrary.SDendaccess(id); 1083 } 1084 catch (HDFException ex) { 1085 log.debug("SDendaccess failure: ", ex); 1086 } 1087 } 1088 1089 // check if the given SDS has dimension metadata 1090 // Coordinate variables are not displayed. They are created to store 1091 // metadata associated with dimensions. To ensure compatibility with 1092 // netCDF, coordinate variables are implemented as data sets 1093 1094 if (isCoordvar) { 1095 objName[0] += " (dimension)"; 1096 } 1097 1098 if (id != HDFConstants.FAIL) { // && !isCoordvar) 1099 long oid[] = { tag, ref }; 1100 1101 if (copyAllowed) { 1102 objList.add(oid); 1103 } 1104 else if (find(oid)) { 1105 return null; 1106 } 1107 1108 sds = new H4SDS(this, objName[0], path, oid); 1109 } 1110 1111 log.trace("getSDS(): finish"); 1112 return sds; 1113 } 1114 1115 /** 1116 * Retrieve a Vdata for the given Vdata identifier and index. 1117 * 1118 * @param ref 1119 * the reference idendifier of the Vdata. 1120 * @param path 1121 * the path of the Vdata. 1122 * @param copyAllowed 1123 * The indicator if multiple copies of an object is allowed. 1124 * 1125 * @return the new H4Vdata if successful; otherwise returns null. 1126 */ 1127 private final H4Vdata getVdata(int tag, int ref, String path, 1128 boolean copyAllowed) { 1129 int id = -1; 1130 H4Vdata vdata = null; 1131 String[] objName = { "" }; 1132 String[] vClass = { "" }; 1133 // int tag = HDFConstants.DFTAG_VS; 1134 long oid[] = { tag, ref }; 1135 1136 log.trace("getVdata(): start"); 1137 if (copyAllowed) { 1138 objList.add(oid); 1139 } 1140 else if (find(oid)) { 1141 return null; 1142 } 1143 1144 try { 1145 id = HDFLibrary.VSattach(fid, ref, "r"); 1146 HDFLibrary.VSgetclass(id, vClass); 1147 vClass[0] = vClass[0].trim(); 1148 HDFLibrary.VSgetname(id, objName); 1149 } 1150 catch (HDFException ex) { 1151 id = HDFConstants.FAIL; 1152 } 1153 finally { 1154 try { 1155 HDFLibrary.VSdetach(id); 1156 } 1157 catch (HDFException ex) { 1158 log.debug("VSdetach failure: ", ex); 1159 } 1160 } 1161 1162 if (showAll || 1163 ((id != HDFConstants.FAIL) 1164 && !vClass[0].equalsIgnoreCase(HDFConstants.HDF_ATTRIBUTE) // do not display Vdata named "Attr0.0" // commented out for bug 1737 1165 && !vClass[0].startsWith(HDFConstants.HDF_CHK_TBL) // do not display internal Vdata, "_HDF_CHK_TBL_" 1166 && !vClass[0].startsWith(HDFConstants.HDF_SDSVAR) // do not display attributes 1167 && !vClass[0].startsWith(HDFConstants.HDF_CRDVAR) 1168 && !vClass[0].startsWith(HDFConstants.DIM_VALS) 1169 && !vClass[0].startsWith(HDFConstants.DIM_VALS01) 1170 && !vClass[0].startsWith(HDFConstants.RIGATTRCLASS) 1171 && !vClass[0].startsWith(HDFConstants.RIGATTRNAME) 1172 && !vClass[0].equalsIgnoreCase(HDFConstants.HDF_CDF))) // do not display internal vdata for CDF, "CDF0.0" 1173 { 1174 vdata = new H4Vdata(this, objName[0], path, oid); 1175 } 1176 1177 log.trace("getVdata(): finish"); 1178 return vdata; 1179 } 1180 1181 /** 1182 * Retrieve a VGroup for the given VGroup identifier and index. 1183 * 1184 * @param ref 1185 * the reference idendifier of the VGroup. 1186 * @param path 1187 * the path of the VGroup. 1188 * @param pgroup 1189 * the parent group. 1190 * @param copyAllowed 1191 * The indicator if multiple copies of an object is allowed. 1192 * 1193 * @return the new H4VGroup if successful; otherwise returns null. 1194 */ 1195 private final H4Group getVGroup(int tag, int ref, String path, 1196 H4Group pgroup, boolean copyAllowed) { 1197 int id = -1; 1198 H4Group vgroup = null; 1199 String[] objName = { "" }; 1200 String[] vClass = { "" }; 1201 // int tag = HDFConstants.DFTAG_VG; 1202 long oid[] = { tag, ref }; 1203 1204 log.trace("getVGroup(): start"); 1205 if (copyAllowed) { 1206 objList.add(oid); 1207 } 1208 else if (find(oid)) { 1209 return null; 1210 } 1211 1212 try { 1213 id = HDFLibrary.Vattach(fid, ref, "r"); 1214 HDFLibrary.Vgetclass(id, vClass); 1215 vClass[0] = vClass[0].trim(); 1216 HDFLibrary.Vgetname(id, objName); 1217 } 1218 catch (HDFException ex) { 1219 id = HDFConstants.FAIL; 1220 } 1221 finally { 1222 try { 1223 HDFLibrary.Vdetach(id); 1224 } 1225 catch (HDFException ex) { 1226 log.debug("Vdetach failure: ", ex); 1227 } 1228 } 1229 1230 // ignore the Vgroups created by the GR interface 1231 if (showAll || ((id != HDFConstants.FAIL) 1232 && !vClass[0].equalsIgnoreCase(HDFConstants.GR_NAME) // do not display Vdata named "Attr0.0" 1233 && !vClass[0].equalsIgnoreCase(HDFConstants.RI_NAME) 1234 && !vClass[0].equalsIgnoreCase(HDFConstants.RIGATTRNAME) 1235 && !vClass[0].equalsIgnoreCase(HDFConstants.RIGATTRCLASS) 1236 && !vClass[0].equalsIgnoreCase(HDFConstants.HDF_CDF))) 1237 { 1238 vgroup = new H4Group(this, objName[0], path, pgroup, oid); 1239 } 1240 1241 log.trace("getVGroup(): finish"); 1242 return vgroup; 1243 } 1244 1245 /** 1246 * Check if object already exists in memory by match the (tag, ref) pairs. 1247 */ 1248 private final boolean find(long[] oid) { 1249 boolean existed = false; 1250 1251 if (objList == null) { 1252 return false; 1253 } 1254 1255 int n = objList.size(); 1256 long[] theOID = null; 1257 1258 for (int i = 0; i < n; i++) { 1259 theOID = (long[]) objList.get(i); 1260 if ((theOID[0] == oid[0]) && (theOID[1] == oid[1])) { 1261 existed = true; 1262 break; 1263 } 1264 } 1265 1266 if (!existed) { 1267 objList.add(oid); 1268 } 1269 1270 return existed; 1271 } 1272 1273 /** 1274 * Returns the GR identifier, which is returned from GRstart(fid). 1275 * 1276 * @return the identifier. 1277 */ 1278 int getGRAccessID() { 1279 return grid; 1280 } 1281 1282 /** 1283 * Returns the SDS identifier, which is returned from SDstart(fname, flag). 1284 * 1285 * @return the identifier. 1286 */ 1287 int getSDAccessID() { 1288 return sdid; 1289 } 1290 1291 /** 1292 * Reads HDF file annotation (file labels and descriptions) into memory. 1293 * The file annotation is stored as attribute of the root group. 1294 * 1295 * @param fid 1296 * the file identifier. 1297 * @param attrList 1298 * the list of attributes. 1299 * 1300 * @return the updated attribute list. 1301 * 1302 * @throws Exception if the annotation can not be read 1303 */ 1304 private List getFileAnnotation(int fid, List attrList) throws HDFException { 1305 if (fid < 0) { 1306 return attrList; 1307 } 1308 1309 int anid = HDFConstants.FAIL; 1310 try { 1311 anid = HDFLibrary.ANstart(fid); 1312 // fileInfo[0] = n_file_label, fileInfo[1] = n_file_desc, 1313 // fileInfo[2] = n_data_label, fileInfo[3] = n_data_desc 1314 int[] fileInfo = new int[4]; 1315 HDFLibrary.ANfileinfo(anid, fileInfo); 1316 1317 if (fileInfo[0] + fileInfo[1] <= 0) { 1318 try { 1319 HDFLibrary.ANend(anid); 1320 } 1321 catch (HDFException ex) { 1322 log.debug("ANend failure: ", ex); 1323 } 1324 return attrList; 1325 } 1326 1327 if (attrList == null) { 1328 attrList = new Vector(fileInfo[0] + fileInfo[1], 5); 1329 } 1330 1331 // load file labels and descriptions 1332 int id = -1; 1333 int[] annTypes = { HDFConstants.AN_FILE_LABEL, 1334 HDFConstants.AN_FILE_DESC }; 1335 for (int j = 0; j < 2; j++) { 1336 String annName = null; 1337 if (j == 0) { 1338 annName = "File Label"; 1339 } 1340 else { 1341 annName = "File Description"; 1342 } 1343 1344 for (int i = 0; i < fileInfo[j]; i++) { 1345 try { 1346 id = HDFLibrary.ANselect(anid, i, annTypes[j]); 1347 } 1348 catch (HDFException ex) { 1349 id = HDFConstants.FAIL; 1350 } 1351 1352 if (id == HDFConstants.FAIL) { 1353 try { 1354 HDFLibrary.ANendaccess(id); 1355 } 1356 catch (HDFException ex) { 1357 log.debug("ANendaccess failure: ", ex); 1358 } 1359 continue; 1360 } 1361 1362 int length = 0; 1363 try { 1364 length = HDFLibrary.ANannlen(id) + 1; 1365 } 1366 catch (HDFException ex) { 1367 length = 0; 1368 } 1369 1370 if (length > 0) { 1371 boolean b = false; 1372 String str[] = { "" }; 1373 try { 1374 b = HDFLibrary.ANreadann(id, str, length); 1375 } 1376 catch (HDFException ex) { 1377 b = false; 1378 } 1379 1380 if (b && (str[0].length() > 0)) { 1381 long attrDims[] = { str[0].length() }; 1382 Attribute newAttr = new Attribute(annName + " #" + i, 1383 new H4Datatype(HDFConstants.DFNT_CHAR), attrDims); 1384 attrList.add(newAttr); 1385 newAttr.setValue(str[0]); 1386 } 1387 } 1388 1389 try { 1390 HDFLibrary.ANendaccess(id); 1391 } 1392 catch (HDFException ex) { 1393 log.debug("ANendaccess failure: ", ex); 1394 } 1395 } // for (int i=0; i < fileInfo[annTYpe]; i++) 1396 } // for (int annType=0; annType<2; annType++) 1397 } 1398 finally { 1399 try { 1400 HDFLibrary.ANend(anid); 1401 } 1402 catch (HDFException ex) { 1403 log.debug("ANend failure: ", ex); 1404 } 1405 } 1406 1407 return attrList; 1408 } 1409 1410 /** 1411 * Reads GR global attributes into memory. The attributes are stored as 1412 * attributes of the root group. 1413 * 1414 * @param grid 1415 * the GR identifier. 1416 * @param attrList 1417 * the list of attributes. 1418 * 1419 * @return the updated attribute list. 1420 * 1421 * @throws HDFException if the GR attributes can not be read 1422 */ 1423 private List getGRglobleAttribute(int grid, List attrList) 1424 throws HDFException { 1425 if (grid == HDFConstants.FAIL) { 1426 return attrList; 1427 } 1428 1429 int[] attrInfo = { 0, 0 }; 1430 HDFLibrary.GRfileinfo(grid, attrInfo); 1431 int numberOfAttributes = attrInfo[1]; 1432 1433 if (numberOfAttributes > 0) { 1434 if (attrList == null) { 1435 attrList = new Vector(numberOfAttributes, 5); 1436 } 1437 1438 String[] attrName = new String[1]; 1439 for (int i = 0; i < numberOfAttributes; i++) { 1440 attrName[0] = ""; 1441 boolean b = false; 1442 try { 1443 b = HDFLibrary.GRattrinfo(grid, i, attrName, attrInfo); 1444 // mask off the litend bit 1445 attrInfo[0] = attrInfo[0] & (~HDFConstants.DFNT_LITEND); 1446 } 1447 catch (HDFException ex) { 1448 b = false; 1449 } 1450 1451 if (!b) { 1452 continue; 1453 } 1454 1455 long[] attrDims = { attrInfo[1] }; 1456 Attribute attr = new Attribute(attrName[0], new H4Datatype(attrInfo[0]), attrDims); 1457 attrList.add(attr); 1458 1459 Object buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]); 1460 try { 1461 HDFLibrary.GRgetattr(grid, i, buf); 1462 } 1463 catch (HDFException ex) { 1464 buf = null; 1465 } 1466 1467 if (buf != null) { 1468 if ((attrInfo[0] == HDFConstants.DFNT_CHAR) 1469 || (attrInfo[0] == HDFConstants.DFNT_UCHAR8)) { 1470 buf = Dataset.byteToString((byte[]) buf, attrInfo[1]); 1471 } 1472 1473 attr.setValue(buf); 1474 } 1475 1476 } // for (int i=0; i<numberOfAttributes; i++) 1477 } // if (b && numberOfAttributes>0) 1478 1479 return attrList; 1480 } 1481 1482 /** 1483 * Reads SDS global attributes into memory. The attributes are stored as 1484 * attributes of the root group. 1485 * 1486 * @param sdid 1487 * the SD identifier. 1488 * @param attrList 1489 * the list of attributes. 1490 * 1491 * @return the updated attribute list. 1492 * 1493 * @throws HDFException if the SDS attributes can not be read 1494 */ 1495 private List getSDSglobleAttribute(int sdid, List attrList) 1496 throws HDFException { 1497 if (sdid == HDFConstants.FAIL) { 1498 return attrList; 1499 } 1500 1501 int[] attrInfo = { 0, 0 }; 1502 HDFLibrary.SDfileinfo(sdid, attrInfo); 1503 1504 int numberOfAttributes = attrInfo[1]; 1505 if (numberOfAttributes > 0) { 1506 if (attrList == null) { 1507 attrList = new Vector(numberOfAttributes, 5); 1508 } 1509 1510 String[] attrName = new String[1]; 1511 for (int i = 0; i < numberOfAttributes; i++) { 1512 attrName[0] = ""; 1513 boolean b = false; 1514 try { 1515 b = HDFLibrary.SDattrinfo(sdid, i, attrName, attrInfo); 1516 // mask off the litend bit 1517 attrInfo[0] = attrInfo[0] & (~HDFConstants.DFNT_LITEND); 1518 } 1519 catch (HDFException ex) { 1520 b = false; 1521 } 1522 1523 if (!b) { 1524 continue; 1525 } 1526 1527 long[] attrDims = { attrInfo[1] }; 1528 Attribute attr = new Attribute(attrName[0], new H4Datatype(attrInfo[0]), attrDims); 1529 attrList.add(attr); 1530 1531 Object buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]); 1532 try { 1533 HDFLibrary.SDreadattr(sdid, i, buf); 1534 } 1535 catch (HDFException ex) { 1536 buf = null; 1537 } 1538 1539 if (buf != null) { 1540 if ((attrInfo[0] == HDFConstants.DFNT_CHAR) 1541 || (attrInfo[0] == HDFConstants.DFNT_UCHAR8)) { 1542 buf = Dataset.byteToString((byte[]) buf, attrInfo[1]); 1543 } 1544 1545 attr.setValue(buf); 1546 } 1547 1548 } // for (int i=0; i<numberOfAttributes; i++) 1549 } // if (b && numberOfAttributes>0) 1550 1551 return attrList; 1552 } 1553 1554 /** 1555 * Returns the version of the HDF4 library. 1556 */ 1557 @Override 1558 public String getLibversion() { 1559 int[] vers = new int[3]; 1560 String ver = "HDF "; 1561 String[] verStr = { "" }; 1562 1563 try { 1564 HDFLibrary.Hgetlibversion(vers, verStr); 1565 } 1566 catch (HDFException ex) { 1567 log.debug("Hgetlibversion failure: ", ex); 1568 } 1569 1570 ver += vers[0] + "." + vers[1] + "." + vers[2]; 1571 log.debug("libversion is {}", ver); 1572 1573 return ver; 1574 } 1575 1576 /** HDF4 library supports netCDF version 2.3.2. It only supports SDS APIs. */ 1577 private boolean isNetCDF(String filename) { 1578 boolean isnetcdf = false; 1579 java.io.RandomAccessFile raf = null; 1580 1581 try { 1582 raf = new java.io.RandomAccessFile(filename, "r"); 1583 } 1584 catch (Exception ex) { 1585 log.debug("RandomAccessFile {}", filename, ex); 1586 try { 1587 raf.close(); 1588 } 1589 catch (Exception ex2) { 1590 log.debug("RAF.close failure: ", ex2); 1591 } 1592 raf = null; 1593 } 1594 1595 if (raf == null) { 1596 return false; 1597 } 1598 1599 byte[] header = new byte[4]; 1600 try { 1601 raf.read(header); 1602 } 1603 catch (Exception ex) { 1604 header = null; 1605 } 1606 1607 if (header != null) { 1608 if ( 1609 // netCDF 1610 ((header[0] == 67) && (header[1] == 68) && (header[2] == 70) && (header[3] == 1))) { 1611 isnetcdf = true; 1612 } 1613 else { 1614 isnetcdf = false; 1615 } 1616 } 1617 1618 try { 1619 raf.close(); 1620 } 1621 catch (Exception ex) { 1622 log.debug("RAF.close failure: ", ex); 1623 } 1624 1625 return isnetcdf; 1626 } 1627 1628 /** 1629 * Get an individual HObject with a given path. It does not load the whole 1630 * file structure. 1631 * 1632 * @param path the path of the object 1633 * 1634 * @throws Exception if the object cannot be found 1635 */ 1636 @Override 1637 public HObject get(String path) throws Exception { 1638 if (objList == null) { 1639 objList = new Vector(); 1640 } 1641 1642 if ((path == null) || (path.length() <= 0)) { 1643 return null; 1644 } 1645 1646 path = path.replace('\\', '/'); 1647 if (!path.startsWith("/")) { 1648 path = "/" + path; 1649 } 1650 1651 String name = null, pPath = null; 1652 boolean isRoot = false; 1653 1654 if (path.equals("/")) { 1655 name = "/"; // the root 1656 isRoot = true; 1657 } 1658 else { 1659 if (path.endsWith("/")) { 1660 path = path.substring(0, path.length() - 2); 1661 } 1662 int idx = path.lastIndexOf('/'); 1663 name = path.substring(idx + 1); 1664 if (idx == 0) { 1665 pPath = "/"; 1666 } 1667 else { 1668 pPath = path.substring(0, idx); 1669 } 1670 } 1671 1672 HObject obj = null; 1673 isReadOnly = false; 1674 1675 if (fid < 0) { 1676 fid = HDFLibrary.Hopen(fullFileName, HDFConstants.DFACC_WRITE); 1677 if (fid < 0) { 1678 isReadOnly = true; 1679 fid = HDFLibrary.Hopen(fullFileName, HDFConstants.DFACC_READ); 1680 } 1681 HDFLibrary.Vstart(fid); 1682 grid = HDFLibrary.GRstart(fid); 1683 sdid = HDFLibrary.SDstart(fullFileName, flag); 1684 } 1685 1686 if (isRoot) { 1687 obj = getRootGroup(); 1688 } 1689 else { 1690 obj = getAttachedObject(pPath, name); 1691 } 1692 1693 return obj; 1694 } 1695 1696 /** get the root group and all the alone objects */ 1697 private H4Group getRootGroup() { 1698 H4Group rootGroup = null; 1699 1700 long[] oid = { 0, 0 }; 1701 int n = 0, ref = -1; 1702 int[] argv = null; 1703 1704 rootGroup = new H4Group(this, "/", null, null, oid); 1705 1706 // get top level VGroup 1707 int[] tmpN = new int[1]; 1708 int[] refs = null; 1709 try { 1710 // first call to get the number of lone Vgroup 1711 n = HDFLibrary.Vlone(fid, tmpN, 0); 1712 refs = new int[n]; 1713 // second call to get the references of all lone Vgroup 1714 n = HDFLibrary.Vlone(fid, refs, n); 1715 } 1716 catch (HDFException ex) { 1717 n = 0; 1718 } 1719 1720 // Iterate through the file to see members of the group 1721 for (int i = 0; i < n; i++) { 1722 ref = refs[i]; 1723 H4Group g = getVGroup(HDFConstants.DFTAG_VG, ref, 1724 HObject.separator, rootGroup, false); 1725 if (g != null) { 1726 rootGroup.addToMemberList(g); 1727 } 1728 } // for (int i=0; i<n; i++) 1729 1730 // get the top level GR images 1731 argv = new int[2]; 1732 boolean b = false; 1733 try { 1734 b = HDFLibrary.GRfileinfo(grid, argv); 1735 } 1736 catch (HDFException ex) { 1737 b = false; 1738 } 1739 1740 if (b) { 1741 n = argv[0]; 1742 for (int i = 0; i < n; i++) { 1743 // no duplicate object at top level 1744 H4GRImage gr = getGRImage(HDFConstants.DFTAG_RIG, i, 1745 HObject.separator, false); 1746 if (gr != null) { 1747 rootGroup.addToMemberList(gr); 1748 } 1749 } // for (int i=0; i<n; i++) 1750 } // if ( grid!=HDFConstants.FAIL && HDFLibrary.GRfileinfo(grid,argv) ) 1751 1752 // get top level SDS 1753 try { 1754 b = HDFLibrary.SDfileinfo(sdid, argv); 1755 } 1756 catch (HDFException ex) { 1757 b = false; 1758 } 1759 1760 if (b) { 1761 n = argv[0]; 1762 1763 for (int i = 0; i < n; i++) { 1764 // no duplicate object at top level 1765 H4SDS sds = getSDS(HDFConstants.DFTAG_NDG, i, 1766 HObject.separator, false); 1767 if (sds != null) { 1768 rootGroup.addToMemberList(sds); 1769 } 1770 } // for (int i=0; i<n; i++) 1771 } // if (sdid != HDFConstants.FAIL && HDFLibrary.SDfileinfo(sdid, argv)) 1772 1773 // get top level VData 1774 try { 1775 n = HDFLibrary.VSlone(fid, tmpN, 0); 1776 refs = new int[n]; 1777 n = HDFLibrary.VSlone(fid, refs, n); 1778 } 1779 catch (HDFException ex) { 1780 n = 0; 1781 } 1782 1783 for (int i = 0; i < n; i++) { 1784 ref = refs[i]; 1785 1786 // no duplicate object at top level 1787 H4Vdata vdata = getVdata(HDFConstants.DFTAG_VS, ref, 1788 HObject.separator, false); 1789 1790 if (vdata != null) { 1791 rootGroup.addToMemberList(vdata); 1792 } 1793 } // for (int i=0; i<n; i++) 1794 1795 if (rootGroup != null) { 1796 // retrieve file annotation, GR and SDS globle attributes 1797 List attributeList = null; 1798 try { 1799 attributeList = rootGroup.getMetadata(); 1800 } 1801 catch (HDFException ex) { 1802 log.debug("rootGroup.getMetadata failure: ", ex); 1803 } 1804 1805 if (attributeList != null) { 1806 try { 1807 getFileAnnotation(fid, attributeList); 1808 } 1809 catch (HDFException ex) { 1810 log.debug("getFileAnnotation failure: ", ex); 1811 } 1812 try { 1813 getGRglobleAttribute(grid, attributeList); 1814 } 1815 catch (HDFException ex) { 1816 log.debug("getGRglobleAttribute failure: ", ex); 1817 } 1818 try { 1819 getSDSglobleAttribute(sdid, attributeList); 1820 } 1821 catch (HDFException ex) { 1822 log.debug("getSDSglobleAttribute failure: ", ex); 1823 } 1824 } 1825 } 1826 1827 return rootGroup; 1828 } 1829 1830 /** get the object attached to a vgroup */ 1831 private HObject getAttachedObject(String path, String name) { 1832 if ((name == null) || (name.length() <= 0)) { 1833 return null; 1834 } 1835 1836 HObject obj = null; 1837 1838 // get top level VGroup 1839 String[] objName = { "" }; 1840 // check if it is an image 1841 int idx = -1; 1842 try { 1843 idx = HDFLibrary.GRnametoindex(grid, name); 1844 } 1845 catch (HDFException ex) { 1846 idx = -1; 1847 } 1848 1849 if (idx >= 0) { 1850 return getGRImage(HDFConstants.DFTAG_RIG, idx, HObject.separator, false); 1851 } 1852 1853 // get top level SDS 1854 try { 1855 idx = HDFLibrary.SDnametoindex(sdid, name); 1856 } 1857 catch (HDFException ex) { 1858 idx = -1; 1859 } 1860 1861 if (idx >= 0) { 1862 return getSDS(HDFConstants.DFTAG_NDG, idx, HObject.separator, false); 1863 } // if (sdid != HDFConstants.FAIL && HDFLibrary.SDfileinfo(sdid, argv)) 1864 1865 int ref = 0; 1866 try { 1867 ref = HDFLibrary.Vfind(fid, name); 1868 } 1869 catch (HDFException ex) { 1870 ref = -1; 1871 } 1872 1873 if (ref > 0) { 1874 long oid[] = { HDFConstants.DFTAG_VG, ref }; 1875 H4Group g = new H4Group(this, objName[0], path, null, oid); 1876 depth_first(null, g); 1877 return g; 1878 } 1879 1880 // get top level VData 1881 try { 1882 ref = HDFLibrary.VSfind(fid, name); 1883 } 1884 catch (HDFException ex) { 1885 ref = -1; 1886 } 1887 1888 if (ref > 0) { 1889 return getVdata(HDFConstants.DFTAG_VS, ref, HObject.separator, false); 1890 } // for (int i=0; i<n; i++) 1891 1892 return obj; 1893 } 1894}