1. package org.apache.xml.dtm;
  2. import java.lang.reflect.Method;
  3. import java.lang.IllegalAccessException;
  4. import java.lang.reflect.InvocationTargetException;
  5. import javax.xml.transform.SourceLocator;
  6. import org.apache.xalan.res.XSLTErrorResources;
  7. import org.apache.xalan.res.XSLMessages;
  8. /**
  9. * This class specifies an exceptional condition that occured
  10. * in the DTM module.
  11. */
  12. public class DTMException extends RuntimeException {
  13. /** Field locator specifies where the error occured.
  14. * @serial */
  15. SourceLocator locator;
  16. /**
  17. * Method getLocator retrieves an instance of a SourceLocator
  18. * object that specifies where an error occured.
  19. *
  20. * @return A SourceLocator object, or null if none was specified.
  21. */
  22. public SourceLocator getLocator() {
  23. return locator;
  24. }
  25. /**
  26. * Method setLocator sets an instance of a SourceLocator
  27. * object that specifies where an error occured.
  28. *
  29. * @param location A SourceLocator object, or null to clear the location.
  30. */
  31. public void setLocator(SourceLocator location) {
  32. locator = location;
  33. }
  34. /** Field containedException specifies a wrapped exception. May be null.
  35. * @serial */
  36. Throwable containedException;
  37. /**
  38. * This method retrieves an exception that this exception wraps.
  39. *
  40. * @return An Throwable object, or null.
  41. * @see #getCause
  42. */
  43. public Throwable getException() {
  44. return containedException;
  45. }
  46. /**
  47. * Returns the cause of this throwable or <code>null</code> if the
  48. * cause is nonexistent or unknown. (The cause is the throwable that
  49. * caused this throwable to get thrown.)
  50. */
  51. public Throwable getCause() {
  52. return ((containedException == this)
  53. ? null
  54. : containedException);
  55. }
  56. /**
  57. * Initializes the <i>cause</i> of this throwable to the specified value.
  58. * (The cause is the throwable that caused this throwable to get thrown.)
  59. *
  60. * <p>This method can be called at most once. It is generally called from
  61. * within the constructor, or immediately after creating the
  62. * throwable. If this throwable was created
  63. * with {@link #DTMException(Throwable)} or
  64. * {@link #DTMException(String,Throwable)}, this method cannot be called
  65. * even once.
  66. *
  67. * @param cause the cause (which is saved for later retrieval by the
  68. * {@link #getCause()} method). (A <tt>null</tt> value is
  69. * permitted, and indicates that the cause is nonexistent or
  70. * unknown.)
  71. * @return a reference to this <code>Throwable</code> instance.
  72. * @throws IllegalArgumentException if <code>cause</code> is this
  73. * throwable. (A throwable cannot
  74. * be its own cause.)
  75. * @throws IllegalStateException if this throwable was
  76. * created with {@link #DTMException(Throwable)} or
  77. * {@link #DTMException(String,Throwable)}, or this method has already
  78. * been called on this throwable.
  79. */
  80. public synchronized Throwable initCause(Throwable cause) {
  81. if ((this.containedException == null) && (cause != null)) {
  82. throw new IllegalStateException(XSLMessages.createMessage(XSLTErrorResources.ER_CANNOT_OVERWRITE_CAUSE, null)); //"Can't overwrite cause");
  83. }
  84. if (cause == this) {
  85. throw new IllegalArgumentException(
  86. XSLMessages.createMessage(XSLTErrorResources.ER_SELF_CAUSATION_NOT_PERMITTED, null)); //"Self-causation not permitted");
  87. }
  88. this.containedException = cause;
  89. return this;
  90. }
  91. /**
  92. * Create a new DTMException.
  93. *
  94. * @param message The error or warning message.
  95. */
  96. public DTMException(String message) {
  97. super(message);
  98. this.containedException = null;
  99. this.locator = null;
  100. }
  101. /**
  102. * Create a new DTMException wrapping an existing exception.
  103. *
  104. * @param e The exception to be wrapped.
  105. */
  106. public DTMException(Throwable e) {
  107. super(e.getMessage());
  108. this.containedException = e;
  109. this.locator = null;
  110. }
  111. /**
  112. * Wrap an existing exception in a DTMException.
  113. *
  114. * <p>This is used for throwing processor exceptions before
  115. * the processing has started.</p>
  116. *
  117. * @param message The error or warning message, or null to
  118. * use the message from the embedded exception.
  119. * @param e Any exception
  120. */
  121. public DTMException(String message, Throwable e) {
  122. super(((message == null) || (message.length() == 0))
  123. ? e.getMessage()
  124. : message);
  125. this.containedException = e;
  126. this.locator = null;
  127. }
  128. /**
  129. * Create a new DTMException from a message and a Locator.
  130. *
  131. * <p>This constructor is especially useful when an application is
  132. * creating its own exception from within a DocumentHandler
  133. * callback.</p>
  134. *
  135. * @param message The error or warning message.
  136. * @param locator The locator object for the error or warning.
  137. */
  138. public DTMException(String message, SourceLocator locator) {
  139. super(message);
  140. this.containedException = null;
  141. this.locator = locator;
  142. }
  143. /**
  144. * Wrap an existing exception in a DTMException.
  145. *
  146. * @param message The error or warning message, or null to
  147. * use the message from the embedded exception.
  148. * @param locator The locator object for the error or warning.
  149. * @param e Any exception
  150. */
  151. public DTMException(String message, SourceLocator locator,
  152. Throwable e) {
  153. super(message);
  154. this.containedException = e;
  155. this.locator = locator;
  156. }
  157. /**
  158. * Get the error message with location information
  159. * appended.
  160. */
  161. public String getMessageAndLocation() {
  162. StringBuffer sbuffer = new StringBuffer();
  163. String message = super.getMessage();
  164. if (null != message) {
  165. sbuffer.append(message);
  166. }
  167. if (null != locator) {
  168. String systemID = locator.getSystemId();
  169. int line = locator.getLineNumber();
  170. int column = locator.getColumnNumber();
  171. if (null != systemID) {
  172. sbuffer.append("; SystemID: ");
  173. sbuffer.append(systemID);
  174. }
  175. if (0 != line) {
  176. sbuffer.append("; Line#: ");
  177. sbuffer.append(line);
  178. }
  179. if (0 != column) {
  180. sbuffer.append("; Column#: ");
  181. sbuffer.append(column);
  182. }
  183. }
  184. return sbuffer.toString();
  185. }
  186. /**
  187. * Get the location information as a string.
  188. *
  189. * @return A string with location info, or null
  190. * if there is no location information.
  191. */
  192. public String getLocationAsString() {
  193. if (null != locator) {
  194. StringBuffer sbuffer = new StringBuffer();
  195. String systemID = locator.getSystemId();
  196. int line = locator.getLineNumber();
  197. int column = locator.getColumnNumber();
  198. if (null != systemID) {
  199. sbuffer.append("; SystemID: ");
  200. sbuffer.append(systemID);
  201. }
  202. if (0 != line) {
  203. sbuffer.append("; Line#: ");
  204. sbuffer.append(line);
  205. }
  206. if (0 != column) {
  207. sbuffer.append("; Column#: ");
  208. sbuffer.append(column);
  209. }
  210. return sbuffer.toString();
  211. } else {
  212. return null;
  213. }
  214. }
  215. /**
  216. * Print the the trace of methods from where the error
  217. * originated. This will trace all nested exception
  218. * objects, as well as this object.
  219. */
  220. public void printStackTrace() {
  221. printStackTrace(new java.io.PrintWriter(System.err, true));
  222. }
  223. /**
  224. * Print the the trace of methods from where the error
  225. * originated. This will trace all nested exception
  226. * objects, as well as this object.
  227. * @param s The stream where the dump will be sent to.
  228. */
  229. public void printStackTrace(java.io.PrintStream s) {
  230. printStackTrace(new java.io.PrintWriter(s));
  231. }
  232. /**
  233. * Print the the trace of methods from where the error
  234. * originated. This will trace all nested exception
  235. * objects, as well as this object.
  236. * @param s The writer where the dump will be sent to.
  237. */
  238. public void printStackTrace(java.io.PrintWriter s) {
  239. if (s == null) {
  240. s = new java.io.PrintWriter(System.err, true);
  241. }
  242. try {
  243. String locInfo = getLocationAsString();
  244. if (null != locInfo) {
  245. s.println(locInfo);
  246. }
  247. super.printStackTrace(s);
  248. } catch (Throwable e) {}
  249. Throwable exception = getException();
  250. for (int i = 0; (i < 10) && (null != exception); i++) {
  251. s.println("---------");
  252. try {
  253. if (exception instanceof DTMException) {
  254. String locInfo =
  255. ((DTMException) exception)
  256. .getLocationAsString();
  257. if (null != locInfo) {
  258. s.println(locInfo);
  259. }
  260. }
  261. exception.printStackTrace(s);
  262. } catch (Throwable e) {
  263. s.println("Could not print stack trace...");
  264. }
  265. try {
  266. Method meth =
  267. ((Object) exception).getClass().getMethod("getException",
  268. null);
  269. if (null != meth) {
  270. Throwable prev = exception;
  271. exception = (Throwable) meth.invoke(exception, null);
  272. if (prev == exception) {
  273. break;
  274. }
  275. } else {
  276. exception = null;
  277. }
  278. } catch (InvocationTargetException ite) {
  279. exception = null;
  280. } catch (IllegalAccessException iae) {
  281. exception = null;
  282. } catch (NoSuchMethodException nsme) {
  283. exception = null;
  284. }
  285. }
  286. }
  287. }