You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AbortException.java 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* *******************************************************************
  2. * Copyright (c) 1999-2001 Xerox Corporation,
  3. * 2002 Palo Alto Research Center, Incorporated (PARC).
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Public License v1.0
  7. * which accompanies this distribution and is available at
  8. * http://www.eclipse.org/legal/epl-v10.html
  9. *
  10. * Contributors:
  11. * Xerox/PARC initial implementation
  12. * ******************************************************************/
  13. package org.aspectj.bridge;
  14. import java.io.PrintStream;
  15. import java.io.PrintWriter;
  16. import java.util.ArrayList;
  17. /**
  18. * Signal that a process was aborted before completion. This may contain a structured IMessage which indicates why the process was
  19. * aborted (e.g., the underlying exception). For processes using try/catch to complete a method abruptly but complete the process
  20. * normally (e.g., a test failure causes the test to abort but the reporting and testing continues normally), use the static methods
  21. * to borrow and return a "porter" to avoid the expense of constructing a stack trace each time. A porter stack trace is invalid,
  22. * and it should only be used to convey a message. E.g., to print the stack of the AbortException and any contained message:
  23. *
  24. * <pre>
  25. * catch (AbortException ae) {
  26. * IMessage m = ae.getMessage();
  27. * if (!ae.isPorter()) ae.printStackTrace(System.err);
  28. * Throwable thrown = ae.getThrown();
  29. * if (null != thrown) thrown.printStackTrace(System.err);
  30. * }
  31. * </pre>
  32. *
  33. * @author PARC
  34. * @author Andy Clement
  35. */
  36. public class AbortException extends RuntimeException { // XXX move porters out, handle proxy better
  37. private static final long serialVersionUID = -7211791639898586417L;
  38. private boolean isSilent = false;
  39. /** used when message text is null */
  40. public static final String NO_MESSAGE_TEXT = "AbortException (no message)";
  41. private static final ArrayList<AbortException> porters = new ArrayList<>();
  42. /**
  43. * Get a porter exception from the pool. Porter exceptions do <b>not</b> have valid stack traces. They are used only to avoid
  44. * generating stack traces when using throw/catch to abruptly complete but continue.
  45. */
  46. public static AbortException borrowPorter(IMessage message) {
  47. AbortException result;
  48. synchronized (porters) {
  49. if (porters.size() > 0) {
  50. result = porters.get(0);
  51. } else {
  52. result = new AbortException();
  53. result.setIsSilent(false);
  54. }
  55. }
  56. result.setIMessage(message);
  57. result.isPorter = true;
  58. return result;
  59. }
  60. /**
  61. * Return (or add) a porter exception to the pool.
  62. */
  63. public static void returnPorter(AbortException porter) {
  64. synchronized (porters) {
  65. if (porters.contains(porter)) {
  66. throw new IllegalStateException("already have " + porter);
  67. } else {
  68. porters.add(porter);
  69. }
  70. }
  71. }
  72. /** @return NO_MESSAGE_TEXT or message.getMessage() if not null */
  73. private static String extractMessage(IMessage message) {
  74. if (null == message) {
  75. return NO_MESSAGE_TEXT;
  76. } else {
  77. String m = message.getMessage();
  78. if (null == m) {
  79. return NO_MESSAGE_TEXT;
  80. } else {
  81. return m;
  82. }
  83. }
  84. }
  85. /** structured message abort */
  86. protected IMessage message;
  87. /** true if this is a porter exception - only used to hold message */
  88. protected boolean isPorter;
  89. /** abort with default String message */
  90. public AbortException() {
  91. this("ABORT");
  92. isSilent = true;
  93. }
  94. /** abort with message */
  95. public AbortException(String s) {
  96. super(null != s ? s : NO_MESSAGE_TEXT);
  97. this.message = null;
  98. }
  99. /** abort with structured message */
  100. public AbortException(IMessage message) {
  101. super(extractMessage(message));
  102. this.message = message;
  103. }
  104. /** @return IMessage structured message, if set */
  105. public IMessage getIMessage() {
  106. return message;
  107. }
  108. /**
  109. * The stack trace of a porter is invalid; it is only used to carry a message (which may itself have a wrapped exception).
  110. *
  111. * @return true if this exception is only to carry exception
  112. */
  113. public boolean isPorter() {
  114. return isPorter;
  115. }
  116. /** @return Throwable at bottom of IMessage chain, if any */
  117. public Throwable getThrown() {
  118. Throwable result = null;
  119. IMessage m = getIMessage();
  120. if (null != m) {
  121. result = m.getThrown();
  122. if (result instanceof AbortException) {
  123. return ((AbortException) result).getThrown();
  124. }
  125. }
  126. return result;
  127. }
  128. private void setIMessage(IMessage message) {
  129. this.message = message;
  130. }
  131. // ----------- proxy attempts
  132. /**
  133. * Get message for this AbortException, either associated explicitly as message or implicitly as IMessage message or its thrown
  134. * message.
  135. *
  136. * @see java.lang.Throwable#getMessage()
  137. */
  138. public String getMessage() {
  139. String message = super.getMessage();
  140. if ((null == message) || (NO_MESSAGE_TEXT == message)) {
  141. IMessage m = getIMessage();
  142. if (null != m) {
  143. message = m.getMessage();
  144. if (null == message) {
  145. Throwable thrown = m.getThrown();
  146. if (null != thrown) {
  147. message = thrown.getMessage();
  148. }
  149. }
  150. }
  151. if (null == message) {
  152. message = NO_MESSAGE_TEXT; // better than nothing
  153. }
  154. }
  155. return message;
  156. }
  157. /**
  158. * @see java.lang.Throwable#printStackTrace()
  159. */
  160. public void printStackTrace() {
  161. printStackTrace(System.out);
  162. }
  163. /**
  164. * Print the stack trace of any enclosed thrown or this otherwise.
  165. *
  166. * @see java.lang.Throwable#printStackTrace(PrintStream)
  167. */
  168. public void printStackTrace(PrintStream s) {
  169. IMessage m = getIMessage();
  170. Throwable thrown = (null == m ? null : m.getThrown());
  171. if (!isPorter() || (null == thrown)) {
  172. s.println("Message: " + m);
  173. super.printStackTrace(s);
  174. } else {
  175. thrown.printStackTrace(s);
  176. }
  177. }
  178. /**
  179. * Print the stack trace of any enclosed thrown or this otherwise.
  180. *
  181. * @see java.lang.Throwable#printStackTrace(PrintWriter)
  182. */
  183. public void printStackTrace(PrintWriter s) {
  184. IMessage m = getIMessage();
  185. Throwable thrown = (null == m ? null : m.getThrown());
  186. if (null == thrown) { // Always print
  187. if (isPorter()) {
  188. s.println("(Warning porter AbortException without thrown)");
  189. }
  190. s.println("Message: " + m);
  191. super.printStackTrace(s);
  192. } else {
  193. thrown.printStackTrace(s);
  194. }
  195. }
  196. public boolean isSilent() {
  197. return isSilent;
  198. }
  199. public void setIsSilent(boolean isSilent) {
  200. this.isSilent = isSilent;
  201. }
  202. }