/**************************************************************************** * 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);
}