1 package cz.cuni.amis.utils.exception; 2 3 import java.util.logging.Logger; 4 5 import cz.cuni.amis.utils.ExceptionToString; 6 import java.util.logging.Level; 7 8 /** 9 * Ancestor of all exceptions of the Pogamut platform (except PogamutIOException and PogamutRuntimeException). It automatically logs the exception to the 10 * platform log of the respective agent were the exception occurred. 11 * <p><p> 12 * Note that Pogamut exceptions are storing the information whether they have been already logged + the instance 13 * of the object that has created (thrown) them. 14 * <p><p> 15 * Because of the 'origin' object you don't have to bother to prefix your exceptions with origin's name. 16 * All you have to care about is to have properly implemented toString() method of your objects 17 * so the messages looks pretty. 18 * <p><p> 19 * By design-choice, every PogamutException is RuntimeException - note that if exception is thrown you will 20 * probably just tore down everything or propagate it higher - no need to write throws to every method 21 * just because we want to state that something might throw an exception. 22 * 23 * @author Jimmy 24 */ 25 @SuppressWarnings("serial") 26 public class PogamutException extends RuntimeException { 27 28 /** 29 * Whether the exception has been logged to the Platform logger 30 */ 31 private boolean hasBeenLogged = false; 32 33 /** 34 * Object that has thrown this exception. 35 */ 36 private Object origin; 37 38 /** 39 * Constructs exception based on the cause an origin. 40 * @param cause 41 * @param origin may be null 42 */ 43 public PogamutException(Throwable cause, Object origin) { 44 super(cause); 45 this.origin = origin; 46 } 47 48 /** 49 * Constructs a new exception with the specified detail message. 50 * <p><p> 51 * Not logging anything anywhere on its own. 52 * 53 * @param message 54 * @param origin which object does produced the exception 55 */ 56 public PogamutException(String message, Object origin) { 57 super(origin.toString() + ": " + message); 58 this.origin = origin; 59 } 60 61 /** 62 * Constructs a new exception with the specified detail message. 63 * <p><p> 64 * Not logging anything anywhere on its own. 65 * 66 * @param message 67 * @param cause 68 */ 69 public PogamutException(String message, Throwable cause) { 70 super(message, cause); 71 this.origin = cause; 72 } 73 74 /** 75 * Constructs a new exception with the specified detail message and cause. 76 * <p><p> 77 * Not logging anything anywhere on its own. 78 * 79 * @param message 80 * @param cause 81 * @param origin object that thrown the exception, may be null 82 */ 83 public PogamutException(String message, Throwable cause, Object origin) { 84 super((origin == null ? "" : origin.toString() + ": ") + message + " (caused by: " + cause.getMessage() + ")", cause); 85 this.origin = origin; 86 } 87 88 89 /** 90 * Constructs a new exception with the specified detail message. 91 * <p><p> 92 * Logs the exception via specified Logger. 93 * 94 * @param message 95 * @param origin which object does produced the exception, may be null 96 */ 97 public PogamutException(String message, Logger log, Object origin){ 98 super((origin == null ? "" : origin.toString() + ": ") + message); 99 this.origin = origin; 100 logException(log); 101 } 102 103 /** 104 * Constructs a new exception with the specified detail message and cause. 105 * <p><p> 106 * Logs the exception via specified Logger. 107 * 108 * @param message 109 * @param cause 110 * @param origin object that thrown the exception 111 */ 112 public PogamutException(Throwable cause, Logger log, Object origin) { 113 super(cause); 114 this.origin = origin; 115 logException(log); 116 } 117 118 /** 119 * Constructs a new exception with the specified detail message and cause. 120 * <p><p> 121 * Logs the exception via specified Logger. 122 * 123 * @param message 124 * @param cause 125 * @param origin object that thrown the exception, may be null 126 */ 127 public PogamutException(String message, Throwable cause, Logger log, Object origin) { 128 super((origin == null ? "" : origin.toString() + ": ") + message + " (caused by: " + cause.getMessage() + ")", cause); 129 this.origin = origin; 130 logException(log); 131 } 132 133 /** 134 * Whether the exception has been logged to any logger. 135 * <p><p> 136 * Note that sometimes it's not possible to log the exception as it is created 137 * due to lack of the logger - therefore we propagate this information through 138 * the stack and as soon as it encounters some Pogamut-platform catch block 139 * it will be logged. 140 * 141 * @return 142 */ 143 public boolean isLogged() { 144 return hasBeenLogged; 145 } 146 147 /** 148 * Set whether the exception has been logged to the Platform logger, if not 149 * it will be logged as soon as it encounters some catch block from the Pogamut 150 * platform. 151 * 152 * @param logged 153 */ 154 public void setLogged(boolean logged) { 155 this.hasBeenLogged = logged; 156 } 157 158 /** 159 * Returns the object that has thrown the exception. 160 * @return 161 */ 162 public Object getOrigin() { 163 return origin; 164 } 165 166 /** 167 * Serialize the exception to String. 168 */ 169 public String toString() { 170 if (this == null) return "PogamutException-instantiating"; 171 return getClass().getSimpleName() + "[" + getMessage() + "]"; 172 } 173 174 /** 175 * Logs the exception to the log + sets isLogged() to true. 176 */ 177 public synchronized void logException(Logger log) { 178 try { 179 if (log == null) return; 180 if (log.isLoggable(Level.SEVERE)) log.severe(ExceptionToString.process(getMessage(), this)); 181 this.hasBeenLogged = true; 182 } catch (Exception e) { 183 System.err.println("PogamutException (and can't log to log '"+log.getName()+"' because \""+e.getMessage()+"\"), exception: " + toString()); 184 this.printStackTrace(System.err); 185 } 186 } 187 188 /** 189 * Logs the exception to the log iff !isLogged(). 190 * <p><p> 191 * Logs the exception only once! Successive calls do nothing. 192 */ 193 public synchronized void logExceptionOnce(Logger log) { 194 if (log == null) return; 195 if (isLogged()) return; 196 logException(log); 197 } 198 199 }