View Javadoc

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 }