001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2008
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.shared.exceptions;
034:
035: import com.flexive.shared.FxLanguage;
036: import com.flexive.shared.LogLevel;
037: import com.flexive.shared.security.UserTicket;
038: import org.apache.commons.logging.Log;
039:
040: /**
041: * Base class for all [fleXive] Exceptions, supports localized messages and converting.
042: * Refer to the property files in package com.flexive.shared.exception.messages for keys to use.
043: * All property files in this package will be concatenated to one big FxExceptionMessages.properties file
044: * upon deployment.
045: * If a (not null) Logger is passed as the first argument the message will be logged at level "error" in the default
046: * locale (usually english) as well.
047: *
048: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
049: */
050: public class FxApplicationException extends Exception implements
051: FxLocalizedException {
052: private static final long serialVersionUID = 2510161167326772282L;
053:
054: /**
055: * the localized message
056: */
057: protected FxExceptionMessage message;
058:
059: /**
060: * was the message logged?
061: */
062: private boolean messageLogged = false;
063: private String affectedXPath = "";
064:
065: /**
066: * Localized exception constructor
067: *
068: * @param converted the message to convert
069: */
070: public FxApplicationException(FxApplicationException converted) {
071: super (converted.message.getKey());
072: this .message = converted.message;
073: }
074:
075: /**
076: * Localized exception constructor
077: *
078: * @param log Log to use
079: * @param converted exception to convert
080: */
081: public FxApplicationException(Log log,
082: FxApplicationException converted) {
083: super (converted.message.getKey());
084: this .message = converted.message;
085: if (log != null && !converted.messageLogged())
086: this .logMessage(log, this .getMessage(), null);
087: }
088:
089: /**
090: * Has the message been logged?
091: *
092: * @return message logged
093: */
094: protected boolean messageLogged() {
095: return this .messageLogged;
096: }
097:
098: /**
099: * Get the XPath that has caused this Exception to be thrown
100: *
101: * @return affected XPath or empty String if not XPath related
102: */
103: public String getAffectedXPath() {
104: return affectedXPath;
105: }
106:
107: /**
108: * Is this exception related to an XPath?
109: *
110: * @return exception related to an XPath
111: */
112: public boolean hasAffectedXPath() {
113: return !"".equals(affectedXPath);
114: }
115:
116: /**
117: * Set the affected XPath that caused this Exception to be thrown
118: *
119: * @param affectedXPath XPath that caused this Exception to be thrown
120: * @return this
121: */
122: public FxApplicationException setAffectedXPath(String affectedXPath) {
123: if (affectedXPath != null)
124: this .affectedXPath = affectedXPath;
125: return this ;
126: }
127:
128: /**
129: * Log a message at a given level (or error if no level given)
130: *
131: * @param log Log to use
132: * @param message magges to LOG
133: * @param level log4j level to apply
134: */
135: private void logMessage(Log log, String message, LogLevel level) {
136: this .messageLogged = true;
137: final Throwable cause = getCause() != null ? getCause() : this ;
138: if (level == null)
139: log.error(message, cause);
140: else {
141: switch (level) {
142: case DEBUG:
143: if (log.isDebugEnabled())
144: log.debug(message);
145: break;
146: case ERROR:
147: if (log.isErrorEnabled())
148: log.error(message, cause);
149: break;
150: case FATAL:
151: if (log.isFatalEnabled())
152: log.fatal(message, cause);
153: break;
154: case INFO:
155: if (log.isInfoEnabled())
156: log.info(message);
157: break;
158: // case Level.WARN_INT:
159: default:
160: if (log.isWarnEnabled())
161: log.warn(message);
162: }
163: }
164: }
165:
166: /**
167: * Localized exception constructor
168: *
169: * @param key exception messge resource key
170: * @param values value parameters for resource message
171: */
172: public FxApplicationException(String key, Object... values) {
173: super (key);
174: this .message = new FxExceptionMessage(key, values);
175: }
176:
177: /**
178: * Localized exception constructor
179: *
180: * @param log Log to use
181: * @param key exception messge resource key
182: * @param values value parameters for resource message
183: */
184: public FxApplicationException(Log log, String key, Object... values) {
185: super (key);
186: this .message = new FxExceptionMessage(key, values);
187: if (log != null)
188: this .logMessage(log, this .getMessage(), null);
189: }
190:
191: /**
192: * Localized exception constructor
193: *
194: * @param cause causing exception
195: * @param key exception messge resource key
196: * @param values value parameters for resource message
197: */
198: public FxApplicationException(Throwable cause, String key,
199: Object... values) {
200: super (key, cause);
201: this .message = new FxExceptionMessage(key, values);
202: }
203:
204: /**
205: * Localized exception constructor
206: *
207: * @param log Log to use
208: * @param cause causing message
209: * @param key exception messge resource key
210: * @param values value parameters for resource message
211: */
212: public FxApplicationException(Log log, Throwable cause, String key,
213: Object... values) {
214: super (key, cause);
215: this .message = new FxExceptionMessage(key, values);
216: if (log != null)
217: this .logMessage(log, this .getMessage(), null);
218: }
219:
220: /**
221: * Localized exception constructor
222: *
223: * @param key exception messge resource key
224: */
225: public FxApplicationException(String key) {
226: super (key);
227: this .message = new FxExceptionMessage(key);
228: }
229:
230: /**
231: * Localized exception constructor
232: *
233: * @param log Log to use
234: * @param key exception messge resource key
235: */
236: public FxApplicationException(Log log, String key) {
237: super (key);
238: this .message = new FxExceptionMessage(key);
239: if (log != null)
240: this .logMessage(log, this .getMessage(), null);
241: }
242:
243: /**
244: * Localized exception constructor
245: *
246: * @param message resource key
247: * @param cause causing exception
248: */
249: public FxApplicationException(String message, Throwable cause) {
250: super (message, cause);
251: this .message = new FxExceptionMessage(message);
252: }
253:
254: /**
255: * Localized exception constructor
256: *
257: * @param log Log to use
258: * @param message resource key
259: * @param cause exception cause
260: */
261: public FxApplicationException(Log log, String message,
262: Throwable cause) {
263: super (message, cause);
264: this .message = new FxExceptionMessage(message);
265: if (log != null)
266: this .logMessage(log, this .getMessage(), null);
267: }
268:
269: /**
270: * Localized exception constructor
271: *
272: * @param cause exception cause
273: */
274: public FxApplicationException(Throwable cause) {
275: super (cause);
276: assignMessage(cause);
277: }
278:
279: /**
280: * Assign a message from another Exception
281: *
282: * @param cause the cause to assign the message to this exception
283: */
284: private void assignMessage(Throwable cause) {
285: if (cause instanceof FxApplicationException)
286: this .message = ((FxApplicationException) cause).message;
287: else
288: this .message = new FxExceptionMessage("ex.native", cause
289: .getClass().getName(), cause.getMessage());
290: }
291:
292: /**
293: * Localized exception constructor
294: *
295: * @param log Log to use
296: * @param cause causing exception
297: */
298: public FxApplicationException(Log log, Throwable cause) {
299: super (cause);
300: assignMessage(cause);
301: if (log != null)
302: this .logMessage(log, this .getMessage(), null);
303: }
304:
305: /**
306: * {@inheritDoc}
307: */
308: public final String getMessage() {
309: return message.getLocalizedMessage(FxLanguage.DEFAULT_ID,
310: FxLanguage.DEFAULT_ISO)
311: + evaluateCause(FxLanguage.DEFAULT_ID);
312: }
313:
314: /**
315: * Return the localized messages of any chained exceptions that are derived from FxException
316: *
317: * @param langCode the language code
318: * @return the localized messages of any chained exceptions that are derived from FxException
319: */
320: private String evaluateCause(long langCode) {
321: Throwable org = this .getCause();
322: String msg = "";
323: while (org != null) {
324: if (org instanceof FxApplicationException) {
325: if (!this .message
326: .equals(((FxApplicationException) org).message))
327: msg += ((FxApplicationException) org).message
328: .getLocalizedMessage(langCode);
329: }
330: org = org.getCause();
331: }
332: return msg;
333: }
334:
335: /**
336: * {@inheritDoc}
337: */
338: public String getMessage(FxLanguage locale) {
339: return message.getLocalizedMessage(locale)
340: + evaluateCause(locale.getId());
341: }
342:
343: /**
344: * {@inheritDoc}
345: */
346: public String getMessage(long localeId) {
347: return message.getLocalizedMessage(localeId)
348: + evaluateCause(localeId);
349: }
350:
351: /**
352: * {@inheritDoc}
353: */
354: public String getMessage(UserTicket ticket) {
355: if (ticket != null)
356: return message.getLocalizedMessage(ticket.getLanguage())
357: + evaluateCause(ticket.getLanguage().getId());
358: else
359: return this .getMessage();
360: }
361:
362: /**
363: * {@inheritDoc}
364: */
365: public FxExceptionMessage getExceptionMessage() {
366: return message;
367: }
368:
369: /**
370: * Wraps this exception in a FxRuntimeException.
371: *
372: * @return this exception wrapped in a FxRuntimeException.
373: */
374: public FxRuntimeException asRuntimeException() {
375: FxRuntimeException exception = new FxRuntimeException(this );
376: // keep our stack trace
377: exception.setStackTrace(this.getStackTrace());
378: return exception;
379: }
380: }
|