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.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 1593 Object buf = null; 1594 try { 1595 buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]); 1596 } 1597 catch (OutOfMemoryError e) { 1598 log.debug("getGRglobalAttribute(): out of memory: ", e); 1599 buf = null; 1600 } 1601 1602 try { 1603 HDFLibrary.GRgetattr(grid, i, buf); 1604 } 1605 catch (HDFException ex) { 1606 log.debug("getGRglobalAttribute(): GRgetattr failure: ", ex); 1607 buf = null; 1608 } 1609 1610 if (buf != null) { 1611 if ((attrInfo[0] == HDFConstants.DFNT_CHAR) 1612 || (attrInfo[0] == HDFConstants.DFNT_UCHAR8)) { 1613 buf = Dataset.byteToString((byte[]) buf, attrInfo[1]); 1614 attrDims[0] = ((String[]) buf).length; 1615 } 1616 } 1617 1618 Attribute attr = new Attribute(getRootObject(), attrName[0], new H4Datatype(attrInfo[0]), attrDims, buf); 1619 attrList.add(attr); 1620 } // for (int i=0; i<numberOfAttributes; i++) 1621 } // if (b && numberOfAttributes>0) 1622 1623 log.trace("getGRglobalAttribute(): finish"); 1624 return attrList; 1625 } 1626 1627 /** 1628 * Reads SDS global attributes into memory. The attributes are stored as 1629 * attributes of the root group. 1630 * 1631 * @param sdid 1632 * the SD identifier. 1633 * @param attrList 1634 * the list of attributes. 1635 * 1636 * @return the updated attribute list. 1637 * 1638 * @throws HDFException if the SDS attributes can not be read 1639 */ 1640 @SuppressWarnings({"rawtypes", "unchecked"}) 1641 private List getSDSglobalAttribute(long sdid, List attrList) 1642 throws HDFException { 1643 log.trace("getSDSglobalAttribute(): start: SDID:{}", sdid); 1644 1645 if (sdid == HDFConstants.FAIL) { 1646 log.debug("getSDSglobalAttribute(): Invalid SDID"); 1647 log.trace("getSDSglobalAttribute(): finish"); 1648 return attrList; 1649 } 1650 1651 int[] attrInfo = { 0, 0 }; 1652 HDFLibrary.SDfileinfo(sdid, attrInfo); 1653 1654 int numberOfAttributes = attrInfo[1]; 1655 if (numberOfAttributes > 0) { 1656 if (attrList == null) { 1657 attrList = new Vector(numberOfAttributes, 5); 1658 } 1659 1660 String[] attrName = new String[1]; 1661 for (int i = 0; i < numberOfAttributes; i++) { 1662 attrName[0] = ""; 1663 boolean b = false; 1664 try { 1665 b = HDFLibrary.SDattrinfo(sdid, i, attrName, attrInfo); 1666 // mask off the litend bit 1667 attrInfo[0] = attrInfo[0] & (~HDFConstants.DFNT_LITEND); 1668 } 1669 catch (HDFException ex) { 1670 log.debug("getSDSglobalAttribute(): SDattrinfo failure: ", ex); 1671 b = false; 1672 } 1673 1674 if (!b) { 1675 continue; 1676 } 1677 1678 long[] attrDims = { attrInfo[1] }; 1679 1680 Object buf = null; 1681 try { 1682 buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]); 1683 } 1684 catch (OutOfMemoryError e) { 1685 log.debug("getSDSglobalAttribute(): out of memory: ", e); 1686 buf = null; 1687 } 1688 1689 try { 1690 HDFLibrary.SDreadattr(sdid, i, buf); 1691 } 1692 catch (HDFException ex) { 1693 log.debug("getSDSglobalAttribute(): SDreadattr failure: ", ex); 1694 buf = null; 1695 } 1696 1697 if (buf != null) { 1698 if ((attrInfo[0] == HDFConstants.DFNT_CHAR) 1699 || (attrInfo[0] == HDFConstants.DFNT_UCHAR8)) { 1700 buf = Dataset.byteToString((byte[]) buf, attrInfo[1]); 1701 attrDims[0] = ((String[]) buf).length; 1702 } 1703 } 1704 1705 Attribute attr = new Attribute(getRootObject(), attrName[0], new H4Datatype(attrInfo[0]), attrDims, buf); 1706 attrList.add(attr); 1707 } // for (int i=0; i<numberOfAttributes; i++) 1708 } // if (b && numberOfAttributes>0) 1709 1710 log.trace("getSDSglobalAttribute(): finish"); 1711 return attrList; 1712 } 1713 1714 /** 1715 * Returns the version of the HDF4 library. 1716 */ 1717 @Override 1718 public String getLibversion() { 1719 int[] vers = new int[3]; 1720 String ver = "HDF "; 1721 String[] verStr = { "" }; 1722 1723 try { 1724 HDFLibrary.Hgetlibversion(vers, verStr); 1725 } 1726 catch (HDFException ex) { 1727 log.debug("getLibVersion(): Hgetlibversion failure: ", ex); 1728 } 1729 1730 ver += vers[0] + "." + vers[1] + "." + vers[2]; 1731 log.debug("getLibversion(): libversion is {}", ver); 1732 1733 return ver; 1734 } 1735 1736 /** HDF4 library supports netCDF version 2.3.2. It only supports SDS APIs. */ 1737 private boolean isNetCDF(String filename) { 1738 log.trace("isNetCDF(): start: filename={}", filename); 1739 1740 boolean isnetcdf = false; 1741 java.io.RandomAccessFile raf = null; 1742 1743 try { 1744 raf = new java.io.RandomAccessFile(filename, "r"); 1745 } 1746 catch (Exception ex) { 1747 log.debug("RandomAccessFile {}", filename, ex); 1748 try { 1749 raf.close(); 1750 } 1751 catch (Exception ex2) { 1752 log.debug("RAF.close failure: ", ex2); 1753 } 1754 raf = null; 1755 } 1756 1757 if (raf == null) { 1758 log.debug("isNetCDF(): raf is null"); 1759 log.trace("isNetCDF(): finish"); 1760 return false; 1761 } 1762 1763 byte[] header = new byte[4]; 1764 try { 1765 raf.read(header); 1766 } 1767 catch (Exception ex) { 1768 header = null; 1769 } 1770 1771 if (header != null) { 1772 if ( 1773 // netCDF 1774 ((header[0] == 67) && (header[1] == 68) && (header[2] == 70) && (header[3] == 1))) { 1775 isnetcdf = true; 1776 } 1777 else { 1778 isnetcdf = false; 1779 } 1780 } 1781 1782 try { 1783 raf.close(); 1784 } 1785 catch (Exception ex) { 1786 log.debug("RAF.close failure: ", ex); 1787 } 1788 1789 log.trace("isNetCDF(): finish"); 1790 return isnetcdf; 1791 } 1792 1793 /** 1794 * Get an individual HObject with a given path. It does not load the whole 1795 * file structure. 1796 * 1797 * @param path the path of the object 1798 * 1799 * @throws Exception if the object cannot be found 1800 */ 1801 @Override 1802 @SuppressWarnings("rawtypes") 1803 public HObject get(String path) throws Exception { 1804 log.trace("get(): start: path={}", path); 1805 1806 if (objList == null) { 1807 objList = new Vector(); 1808 } 1809 1810 if ((path == null) || (path.length() <= 0)) { 1811 log.debug("get(): path is null or invalid path length"); 1812 log.trace("get(): finish"); 1813 return null; 1814 } 1815 1816 path = path.replace('\\', '/'); 1817 if (!path.startsWith("/")) { 1818 path = "/" + path; 1819 } 1820 1821 String name = null, pPath = null; 1822 boolean isRoot = false; 1823 1824 if (path.equals("/")) { 1825 name = "/"; // the root 1826 isRoot = true; 1827 } 1828 else { 1829 if (path.endsWith("/")) { 1830 path = path.substring(0, path.length() - 2); 1831 } 1832 int idx = path.lastIndexOf('/'); 1833 name = path.substring(idx + 1); 1834 if (idx == 0) { 1835 pPath = "/"; 1836 } 1837 else { 1838 pPath = path.substring(0, idx); 1839 } 1840 } 1841 1842 log.trace("get(): isRoot={}", isRoot); 1843 1844 HObject obj = null; 1845 isReadOnly = false; 1846 1847 if (fid < 0) { 1848 fid = HDFLibrary.Hopen(fullFileName, HDFConstants.DFACC_WRITE); 1849 if (fid < 0) { 1850 isReadOnly = true; 1851 fid = HDFLibrary.Hopen(fullFileName, HDFConstants.DFACC_READ); 1852 } 1853 HDFLibrary.Vstart(fid); 1854 grid = HDFLibrary.GRstart(fid); 1855 sdid = HDFLibrary.SDstart(fullFileName, flag); 1856 } 1857 1858 if (isRoot) { 1859 obj = getRootGroup(); 1860 } 1861 else { 1862 obj = getAttachedObject(pPath, name); 1863 } 1864 1865 log.trace("get(): finish"); 1866 return obj; 1867 } 1868 1869 /** Get the root group and all the alone objects */ 1870 private H4Group getRootGroup() { 1871 log.trace("getRootGroup(): start"); 1872 1873 H4Group rootGroup = null; 1874 1875 long[] oid = { 0, 0 }; 1876 int n = 0, ref = -1; 1877 int[] argv = null; 1878 1879 rootGroup = new H4Group(this, "/", null, null, oid); 1880 1881 // get top level VGroup 1882 int[] tmpN = new int[1]; 1883 int[] refs = null; 1884 try { 1885 // first call to get the number of lone Vgroups 1886 log.trace("getRootGroup(): first call to Vlone, get number of lone Vgroups"); 1887 n = HDFLibrary.Vlone(fid, tmpN, 0); 1888 log.trace("getRootGroup(): number of lone Vgroups={}", n); 1889 refs = new int[n]; 1890 // second call to get the references of all lone Vgroups 1891 log.trace("getRootGroup(): second call to Vlone, get references of lone Vgroups"); 1892 n = HDFLibrary.Vlone(fid, refs, n); 1893 } 1894 catch (HDFException ex) { 1895 log.debug("getRootGroup(): Vlone failure: ", ex); 1896 n = 0; 1897 } 1898 1899 // Iterate through the file to see members of the group 1900 for (int i = 0; i < n; i++) { 1901 ref = refs[i]; 1902 H4Group g = getVGroup(HDFConstants.DFTAG_VG, ref, 1903 HObject.separator, rootGroup, false); 1904 if (g != null) { 1905 rootGroup.addToMemberList(g); 1906 } 1907 } // for (int i=0; i<n; i++) 1908 1909 // get the top level GR images 1910 argv = new int[2]; 1911 boolean b = false; 1912 try { 1913 b = HDFLibrary.GRfileinfo(grid, argv); 1914 } 1915 catch (HDFException ex) { 1916 log.debug("getRootGroup(): GRfileinfo failure: ", ex); 1917 b = false; 1918 } 1919 1920 if (b) { 1921 n = argv[0]; 1922 for (int i = 0; i < n; i++) { 1923 // no duplicate object at top level 1924 H4GRImage gr = getGRImage(HDFConstants.DFTAG_RIG, i, 1925 HObject.separator, false); 1926 if (gr != null) { 1927 rootGroup.addToMemberList(gr); 1928 } 1929 } // for (int i=0; i<n; i++) 1930 } // if ( grid!=HDFConstants.FAIL && HDFLibrary.GRfileinfo(grid,argv) ) 1931 1932 // get top level SDS 1933 try { 1934 b = HDFLibrary.SDfileinfo(sdid, argv); 1935 } 1936 catch (HDFException ex) { 1937 log.debug("getRootGroup(): SDfileinfo failure: ", ex); 1938 b = false; 1939 } 1940 1941 if (b) { 1942 n = argv[0]; 1943 1944 for (int i = 0; i < n; i++) { 1945 // no duplicate object at top level 1946 H4SDS sds = getSDS(HDFConstants.DFTAG_NDG, i, 1947 HObject.separator, false); 1948 if (sds != null) { 1949 rootGroup.addToMemberList(sds); 1950 } 1951 } // for (int i=0; i<n; i++) 1952 } // if (sdid != HDFConstants.FAIL && HDFLibrary.SDfileinfo(sdid, argv)) 1953 1954 // get top level VData 1955 try { 1956 log.trace("getRootGroup(): first call to VSlone, get number of lone VDatas"); 1957 n = HDFLibrary.VSlone(fid, tmpN, 0); 1958 log.trace("getRootGroup(): number of lone Vdatas={}", n); 1959 refs = new int[n]; 1960 log.trace("getRootGroup(): second call to VSlone, get references of lone VDatas"); 1961 n = HDFLibrary.VSlone(fid, refs, n); 1962 } 1963 catch (HDFException ex) { 1964 log.debug("getRootGroup(): VSlone failure: ex"); 1965 n = 0; 1966 } 1967 1968 for (int i = 0; i < n; i++) { 1969 ref = refs[i]; 1970 1971 // no duplicate object at top level 1972 H4Vdata vdata = getVdata(HDFConstants.DFTAG_VS, ref, 1973 HObject.separator, false); 1974 1975 if (vdata != null) { 1976 rootGroup.addToMemberList(vdata); 1977 } 1978 } // for (int i=0; i<n; i++) 1979 1980 if (rootGroup != null) { 1981 // retrieve file annotation, GR and SDS globle attributes 1982 @SuppressWarnings("rawtypes") 1983 List attributeList = null; 1984 try { 1985 attributeList = rootGroup.getMetadata(); 1986 } 1987 catch (HDFException ex) { 1988 log.debug("getRootGroup(): getMetadata() failure: ", ex); 1989 } 1990 1991 if (attributeList != null) { 1992 try { 1993 getFileAnnotation(fid, attributeList); 1994 } 1995 catch (HDFException ex) { 1996 log.debug("getRootGroup(): getFileAnnotation() failure: ", ex); 1997 } 1998 try { 1999 getGRglobalAttribute(grid, attributeList); 2000 } 2001 catch (HDFException ex) { 2002 log.debug("getRootGroup(): getGRglobalAttribute() failure: ", ex); 2003 } 2004 try { 2005 getSDSglobalAttribute(sdid, attributeList); 2006 } 2007 catch (HDFException ex) { 2008 log.debug("getRootGroup(): getSDSglobalAttribute() failure: ", ex); 2009 } 2010 } 2011 } 2012 2013 log.trace("getRootGroup(): finish"); 2014 return rootGroup; 2015 } 2016 2017 /** Get the object attached to a vgroup */ 2018 private HObject getAttachedObject(String path, String name) { 2019 log.trace("getAttachedObject(): start"); 2020 2021 if ((name == null) || (name.length() <= 0)) { 2022 log.debug("getAttachedObject(): name is null or invalid name length"); 2023 log.trace("getAttachedObject(): finish"); 2024 return null; 2025 } 2026 2027 // get top level VGroup 2028 String[] objName = { "" }; 2029 // check if it is an image 2030 int idx = -1; 2031 try { 2032 idx = HDFLibrary.GRnametoindex(grid, name); 2033 } 2034 catch (HDFException ex) { 2035 log.debug("getAttachedObject(): GRnametoindex failure: ", ex); 2036 idx = -1; 2037 } 2038 2039 if (idx >= 0) { 2040 H4GRImage img = getGRImage(HDFConstants.DFTAG_RIG, idx, HObject.separator, false); 2041 log.trace("getAttachedObject(): finish"); 2042 return img; 2043 } 2044 2045 // get top level SDS 2046 try { 2047 idx = HDFLibrary.SDnametoindex(sdid, name); 2048 } 2049 catch (HDFException ex) { 2050 log.debug("getAttachedObject(): SDnametoindex failure: ", ex); 2051 idx = -1; 2052 } 2053 2054 if (idx >= 0) { 2055 H4SDS sds = getSDS(HDFConstants.DFTAG_NDG, idx, HObject.separator, false); 2056 log.trace("getAttachedObject(): finish"); 2057 return sds; 2058 } // if (sdid != HDFConstants.FAIL && HDFLibrary.SDfileinfo(sdid, argv)) 2059 2060 int ref = 0; 2061 try { 2062 ref = HDFLibrary.Vfind(fid, name); 2063 } 2064 catch (HDFException ex) { 2065 log.debug("getAttachedObject(): Vfind failure: ", ex); 2066 ref = -1; 2067 } 2068 2069 if (ref > 0) { 2070 long oid[] = { HDFConstants.DFTAG_VG, ref }; 2071 H4Group g = new H4Group(this, objName[0], path, null, oid); 2072 depth_first(g); 2073 log.trace("getAttachedObject(): finish"); 2074 return g; 2075 } 2076 2077 // get top level VData 2078 try { 2079 ref = HDFLibrary.VSfind(fid, name); 2080 } 2081 catch (HDFException ex) { 2082 log.debug("getAttachedObject(): VSfind failure: ", ex); 2083 ref = -1; 2084 } 2085 2086 if (ref > 0) { 2087 H4Vdata vdata = getVdata(HDFConstants.DFTAG_VS, ref, HObject.separator, false); 2088 log.trace("getAttachedObject(): finish"); 2089 return vdata; 2090 } // for (int i=0; i<n; i++) 2091 2092 log.debug("getAttachedObject(): Object not found"); 2093 log.trace("getAttachedObject(): finish"); 2094 return null; 2095 } 2096 2097 @Override 2098 public void setNewLibBounds(String lowStr, String highStr) throws Exception { 2099 return; 2100 } 2101 2102}