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