/**************************************************************************** * NCSA HDF5 * * National Comptational Science Alliance * * University of Illinois at Urbana-Champaign * * 605 E. Springfield, Champaign IL 61820 * * * * For conditions of distribution and use, see the accompanying * * hdf-java/COPYING file. * * * ****************************************************************************/ package ncsa.hdf.hdf5lib.exceptions; import static ch.systemsx.cisd.hdf5.hdf5lib.H5General.H5open; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.StringWriter; /** *

* The class HDF5LibraryException returns errors raised by the HDF5 library. *

* Each major error code from the HDF-5 Library is represented by a sub-class of this class, and by * default the 'detailedMessage' is set according to the minor error code from the HDF-5 Library. *

* For major and minor error codes, see H5Epublic.h in the HDF-5 library. *

*/ public class HDF5LibraryException extends HDF5Exception { private static final int UNKNOWN = -1; private static final long serialVersionUID = 1L; private final int majorErrorNumber; private final int minorErrorNumber; private final String majorErrorMessage; private final String minorErrorMessage; private final String hdf5ErrorStackString; private final String hdf5ErrorStackLastElementString; /** * Constructs an HDF5LibraryException with the specified detail message. * * @param majorErrorNumber The major error number of the HDF5 library. * @param majorErrorMessage The error message for the major error number of the HDF5 library. * @param minorErrorNumber The minor error number of the HDF5 library. * @param minorErrorMessage The error message for the minor error number of the HDF5 library. */ public HDF5LibraryException(final int majorErrorNumber, final String majorErrorMessage, final int minorErrorNumber, final String minorErrorMessage) { super(majorErrorMessage + ":" + minorErrorMessage); // this code forces the loading of the HDF-5 library // to assure that the native methods are available try { H5open(); } catch (final Exception e) { } this.majorErrorNumber = majorErrorNumber; this.majorErrorMessage = majorErrorMessage; this.minorErrorNumber = minorErrorNumber; this.minorErrorMessage = minorErrorMessage; this.hdf5ErrorStackString = retrieveHDF5ErrorStackAsString(); this.hdf5ErrorStackLastElementString = getLastErrorStackElement(hdf5ErrorStackString); } private static String getLastErrorStackElement(String hdf5ErrorStackString) { int idx = hdf5ErrorStackString.length() - 3; int lastLineBreakIdx = hdf5ErrorStackString.length(); while (--idx > 0) { if (hdf5ErrorStackString.charAt(idx) == '\n') { lastLineBreakIdx = idx; } if (hdf5ErrorStackString.substring(idx - 1, idx + 3).equals("\n #")) { idx += 3; while (idx < hdf5ErrorStackString.length() && hdf5ErrorStackString.charAt(idx) != ' ') { ++idx; } return hdf5ErrorStackString.substring(idx + 1, lastLineBreakIdx); } } return null; } /** * Constructs an HDF5LibraryException with the specified detail message. * * @param errorMessage The error message for the minor error number of the HDF5 library. */ public HDF5LibraryException(final String errorMessage) { super(errorMessage); // this code forces the loading of the HDF-5 library // to assure that the native methods are available try { H5open(); } catch (final Exception e) { } this.majorErrorNumber = UNKNOWN; this.majorErrorMessage = errorMessage; this.minorErrorNumber = UNKNOWN; this.minorErrorMessage = ""; this.hdf5ErrorStackString = "No error stack"; this.hdf5ErrorStackLastElementString = null; } @Override public String getMessage() { if (hdf5ErrorStackLastElementString != null) { return super.getMessage() + " [\"" + hdf5ErrorStackLastElementString + "\"]"; } else { return super.getMessage(); } } /** * Get the major error number of the first error on the HDF5 library error stack. * * @return the major error number */ public int getMajorErrorNumber() { return majorErrorNumber; } /** * Return a error message for the major error number of this exception. *

* These messages come from H5Epublic.h. * * @return the string of the minor error */ public String getMajorError() { return majorErrorMessage; } /** * Get the minor error number of the first error on the HDF5 library error stack. * * @return the minor error number */ public int getMinorErrorNumber() { return minorErrorNumber; } /** * Return a error message for the minor error number of this exception. *

* These messages come from H5Epublic.h. * * @return the string of the minor error */ public String getMinorError() { return minorErrorMessage; } private static FileInputStream openInputStream(File file) throws IOException { if (file.exists()) { if (file.isDirectory()) { throw new IOException("File '" + file + "' exists but is a directory"); } if (file.canRead() == false) { throw new IOException("File '" + file + "' cannot be read"); } } else { throw new FileNotFoundException("File '" + file + "' does not exist"); } return new FileInputStream(file); } /** * Returns the error stack as retrieved from the HDF5 library as a string. */ private String retrieveHDF5ErrorStackAsString() { try { final File tempFile = File.createTempFile("HDF5_error_stack", ".txt"); try { printStackTrace0(tempFile.getPath()); StringWriter sw = new StringWriter(); try (InputStreamReader in = new InputStreamReader(new FileInputStream(tempFile))) { char[] buffer = new char[4096]; int n = 0; while (-1 != (n = in.read(buffer))) { sw.write(buffer, 0, n); } return sw.toString(); } } finally { tempFile.delete(); } } catch (IOException ex) { System.err.println("Cannot create error stack file."); ex.printStackTrace(); return null; } } /** * Returns the error stack from the HDF5 library as a string. */ public String getHDF5ErrorStackAsString() { return hdf5ErrorStackString; } /** * Prints this HDF5LibraryException, the HDF-5 Library error stack, and and the * Java stack trace to the standard error stream. */ @Override public void printStackTrace() { System.err.println(getHDF5ErrorStackAsString()); // the HDF-5 Library error stack super.printStackTrace(); // the Java stack trace } /** * Prints this HDF5LibraryException the HDF-5 Library error stack, and and the Java * stack trace to the specified print stream. */ public void printStackTrace(final java.io.File f) { if ((f == null) || !f.exists() || f.isDirectory() || !f.canWrite()) { printStackTrace(); } else { try { final java.io.FileOutputStream o = new java.io.FileOutputStream(f); final java.io.PrintWriter p = new java.io.PrintWriter(o); p.println(getHDF5ErrorStackAsString()); // the HDF-5 Library error stack super.printStackTrace(p); // the Java stack trace p.close(); } catch (final Exception ex) { System.err.println(this); } } } /* * This private method calls the HDF-5 library to extract the error codes and error stack. */ private native void printStackTrace0(String s); }