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