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