1. /*
  2. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  3. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  4. */
  5. package javax.xml.transform;
  6. import java.lang.reflect.Method;
  7. import java.lang.IllegalAccessException;
  8. import java.lang.reflect.InvocationTargetException;
  9. import javax.xml.transform.SourceLocator;
  10. /**
  11. * This class specifies an exceptional condition that occured
  12. * during the transformation process.
  13. */
  14. public class TransformerException extends Exception {
  15. /** Field locator specifies where the error occured */
  16. SourceLocator locator;
  17. /**
  18. * Method getLocator retrieves an instance of a SourceLocator
  19. * object that specifies where an error occured.
  20. *
  21. * @return A SourceLocator object, or null if none was specified.
  22. */
  23. public SourceLocator getLocator() {
  24. return locator;
  25. }
  26. /**
  27. * Method setLocator sets an instance of a SourceLocator
  28. * object that specifies where an error occured.
  29. *
  30. * @param location A SourceLocator object, or null to clear the location.
  31. */
  32. public void setLocator(SourceLocator location) {
  33. locator = location;
  34. }
  35. /** Field containedException specifies a wrapped exception. May be null. */
  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 #TransformerException(Throwable)} or
  64. * {@link #TransformerException(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 #TransformerException(Throwable)} or
  77. * {@link #TransformerException(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) {
  82. throw new IllegalStateException("Can't overwrite cause");
  83. }
  84. if (cause == this) {
  85. throw new IllegalArgumentException(
  86. "Self-causation not permitted");
  87. }
  88. this.containedException = cause;
  89. return this;
  90. }
  91. /**
  92. * Create a new TransformerException.
  93. *
  94. * @param message The error or warning message.
  95. */
  96. public TransformerException(String message) {
  97. super(message);
  98. this.containedException = null;
  99. this.locator = null;
  100. }
  101. /**
  102. * Create a new TransformerException wrapping an existing exception.
  103. *
  104. * @param e The exception to be wrapped.
  105. */
  106. public TransformerException(Throwable e) {
  107. super(e.toString());
  108. this.containedException = e;
  109. this.locator = null;
  110. }
  111. /**
  112. * Wrap an existing exception in a TransformerException.
  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 TransformerException(String message, Throwable e) {
  122. super(((message == null) || (message.length() == 0))
  123. ? e.toString()
  124. : message);
  125. this.containedException = e;
  126. this.locator = null;
  127. }
  128. /**
  129. * Create a new TransformerException 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 TransformerException(String message, SourceLocator locator) {
  139. super(message);
  140. this.containedException = null;
  141. this.locator = locator;
  142. }
  143. /**
  144. * Wrap an existing exception in a TransformerException.
  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 TransformerException(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. * @return A <code>String</code> representing the error message with
  162. * location information appended.
  163. */
  164. public String getMessageAndLocation() {
  165. StringBuffer sbuffer = new StringBuffer();
  166. String message = super.getMessage();
  167. if (null != message) {
  168. sbuffer.append(message);
  169. }
  170. if (null != locator) {
  171. String systemID = locator.getSystemId();
  172. int line = locator.getLineNumber();
  173. int column = locator.getColumnNumber();
  174. if (null != systemID) {
  175. sbuffer.append("; SystemID: ");
  176. sbuffer.append(systemID);
  177. }
  178. if (0 != line) {
  179. sbuffer.append("; Line#: ");
  180. sbuffer.append(line);
  181. }
  182. if (0 != column) {
  183. sbuffer.append("; Column#: ");
  184. sbuffer.append(column);
  185. }
  186. }
  187. return sbuffer.toString();
  188. }
  189. /**
  190. * Get the location information as a string.
  191. *
  192. * @return A string with location info, or null
  193. * if there is no location information.
  194. */
  195. public String getLocationAsString() {
  196. if (null != locator) {
  197. StringBuffer sbuffer = new StringBuffer();
  198. String systemID = locator.getSystemId();
  199. int line = locator.getLineNumber();
  200. int column = locator.getColumnNumber();
  201. if (null != systemID) {
  202. sbuffer.append("; SystemID: ");
  203. sbuffer.append(systemID);
  204. }
  205. if (0 != line) {
  206. sbuffer.append("; Line#: ");
  207. sbuffer.append(line);
  208. }
  209. if (0 != column) {
  210. sbuffer.append("; Column#: ");
  211. sbuffer.append(column);
  212. }
  213. return sbuffer.toString();
  214. } else {
  215. return null;
  216. }
  217. }
  218. /**
  219. * Print the the trace of methods from where the error
  220. * originated. This will trace all nested exception
  221. * objects, as well as this object.
  222. */
  223. public void printStackTrace() {
  224. printStackTrace(new java.io.PrintWriter(System.err, true));
  225. }
  226. /**
  227. * Print the the trace of methods from where the error
  228. * originated. This will trace all nested exception
  229. * objects, as well as this object.
  230. * @param s The stream where the dump will be sent to.
  231. */
  232. public void printStackTrace(java.io.PrintStream s) {
  233. printStackTrace(new java.io.PrintWriter(s));
  234. }
  235. /**
  236. * Print the the trace of methods from where the error
  237. * originated. This will trace all nested exception
  238. * objects, as well as this object.
  239. * @param s The writer where the dump will be sent to.
  240. */
  241. public void printStackTrace(java.io.PrintWriter s) {
  242. if (s == null) {
  243. s = new java.io.PrintWriter(System.err, true);
  244. }
  245. try {
  246. String locInfo = getLocationAsString();
  247. if (null != locInfo) {
  248. s.println(locInfo);
  249. }
  250. super.printStackTrace(s);
  251. } catch (Throwable e) {}
  252. Throwable exception = getException();
  253. for (int i = 0; (i < 10) && (null != exception); i++) {
  254. s.println("---------");
  255. try {
  256. if (exception instanceof TransformerException) {
  257. String locInfo =
  258. ((TransformerException) exception)
  259. .getLocationAsString();
  260. if (null != locInfo) {
  261. s.println(locInfo);
  262. }
  263. }
  264. exception.printStackTrace(s);
  265. } catch (Throwable e) {
  266. s.println("Could not print stack trace...");
  267. }
  268. try {
  269. Method meth =
  270. ((Object) exception).getClass().getMethod("getException",
  271. null);
  272. if (null != meth) {
  273. Throwable prev = exception;
  274. exception = (Throwable) meth.invoke(exception, null);
  275. if (prev == exception) {
  276. break;
  277. }
  278. } else {
  279. exception = null;
  280. }
  281. } catch (InvocationTargetException ite) {
  282. exception = null;
  283. } catch (IllegalAccessException iae) {
  284. exception = null;
  285. } catch (NoSuchMethodException nsme) {
  286. exception = null;
  287. }
  288. }
  289. s.flush();
  290. }
  291. }