001: /*
002: * Copyright (C) 2007 Rob Manning
003: * manningr@users.sourceforge.net
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019: package net.sourceforge.squirrel_sql.fw.util;
020:
021: import java.sql.DataTruncation;
022: import java.sql.SQLException;
023: import java.sql.SQLWarning;
024:
025: import net.sourceforge.squirrel_sql.fw.sql.SQLExecutionException;
026: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
027: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
028:
029: /**
030: * The default implementation of ExceptionFormatter which is used by Session's
031: * IMessageHandler (MessagePanel) if another one isn't specified by a plugin.
032: * Also, if a custom ExceptionFormatter is stored
033: *
034: * @author manningr
035: */
036: public class DefaultExceptionFormatter implements ExceptionFormatter {
037:
038: /** Logger for this class. */
039: private static final ILogger s_log = LoggerController
040: .createLogger(DefaultExceptionFormatter.class);
041:
042: /**
043: * When a plugin registers it's own ExceptionFormatter for session which
044: * contains this class, this will be non-null
045: */
046: private ExceptionFormatter customFormatter = null;
047:
048: /**
049: * @see net.sourceforge.squirrel_sql.fw.util.ExceptionFormatter#format(java.lang.Throwable)
050: */
051: public String format(Throwable th) {
052: if (th == null) {
053: throw new IllegalArgumentException(
054: "format: th cannot be null");
055: }
056: StringBuilder result = new StringBuilder();
057:
058: String postError = "";
059: Throwable cause = th;
060: if (th instanceof SQLExecutionException) {
061: postError = ((SQLExecutionException) th).getPostError();
062: cause = th.getCause();
063: }
064:
065: String customMessage = null;
066:
067: if (customFormatter != null
068: && customFormatter.formatsException(cause)) {
069: try {
070: customMessage = customFormatter.format(cause);
071: } catch (Exception e) {
072: s_log.error("Exception occurred while formatting: "
073: + e.getMessage(), e);
074: }
075: }
076:
077: if (customMessage != null) {
078: result.append(customMessage);
079: } else {
080: result.append(defaultFormatSQLException(cause));
081: }
082: if (postError != null && !"".equals(postError)) {
083: result.append("\n");
084: result.append(postError);
085: }
086:
087: return result.toString();
088: }
089:
090: public String defaultFormatSQLException(Throwable cause) {
091: StringBuilder result = new StringBuilder();
092: if (cause instanceof DataTruncation) {
093: result
094: .append(getDataTruncationMessage((DataTruncation) cause));
095: } else if (cause instanceof SQLWarning) {
096: result.append(getSQLWarningMessage((SQLWarning) cause));
097: } else if (cause instanceof SQLException) {
098: result.append(getSQLExceptionMessage((SQLException) cause));
099: } else {
100: result.append(cause.toString());
101: }
102: return result.toString();
103: }
104:
105: /**
106: * @see net.sourceforge.squirrel_sql.fw.util.ExceptionFormatter#formatsException(java.lang.Throwable)
107: */
108: public boolean formatsException(Throwable t) {
109: return true;
110: }
111:
112: /**
113: * Sets the custom ExceptionFormatter to delegate calls to format to if the
114: * custom formatter formats the exception.
115: *
116: * @param customFormatter the ExceptionFormatter to delegate calls to. If
117: * one has already been set, this will have no effect
118: * except logging an error message.
119: */
120: public void setCustomExceptionFormatter(
121: ExceptionFormatter customFormatter) {
122: if (customFormatter == null) {
123: throw new IllegalArgumentException(
124: "customFormatter cannot be null");
125: }
126:
127: if (this .customFormatter == null) {
128: this .customFormatter = customFormatter;
129: } else {
130: // Uh-oh! We shouldn't have more than one plugin registering a
131: // custom exception handler for a given session. The first one
132: // wins and all others get an error message.
133: s_log
134: .error("setCustomExceptionFormatter: An existing customFormatter ( "
135: + this .customFormatter.getClass().getName()
136: + " )has already "
137: + "been set - ignoring "
138: + customFormatter.getClass().getName());
139: }
140: }
141:
142: private String getDataTruncationMessage(DataTruncation ex) {
143: StringBuilder buf = new StringBuilder();
144: buf.append("Data Truncation error occured on").append(
145: ex.getRead() ? " a read " : " a write ").append(
146: " of column ").append(ex.getIndex())
147: .append("Data was ").append(ex.getDataSize()).append(
148: " bytes long and ")
149: .append(ex.getTransferSize()).append(
150: " bytes were transferred.");
151: return buf.toString();
152: }
153:
154: private String getSQLWarningMessage(SQLWarning ex) {
155: StringBuilder buf = new StringBuilder();
156: while (ex != null) {
157: buf.append(buildMessage("Warning: ", ex));
158: ex = ex.getNextWarning();
159: }
160:
161: return buf.toString();
162: }
163:
164: private String getSQLExceptionMessage(SQLException ex) {
165: StringBuilder buf = new StringBuilder();
166: while (ex != null) {
167: buf.append(buildMessage("Error: ", ex));
168: if (s_log.isDebugEnabled()) {
169: s_log.debug("Error", ex);
170: }
171: ex = ex.getNextException();
172: if (ex != null) {
173: buf.append("\n");
174: }
175: }
176: return buf.toString();
177: }
178:
179: private String buildMessage(String prefix, SQLException ex) {
180: StringBuilder result = new StringBuilder();
181: result.append(prefix);
182: result.append(ex.getMessage());
183: result.append("\nSQLState: ");
184: result.append(ex.getSQLState());
185: result.append("\nErrorCode: ");
186: result.append(ex.getErrorCode());
187: return result.toString();
188: }
189:
190: }
|