001: /**
002: * Sequoia: Database clustering technology.
003: * Copyright (C) 2005 Emic Networks
004: * Contact: sequoia@continuent.org
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: * Initial developer(s): Marc Herbert
019: * Contributor(s): ______________________.
020: */package org.continuent.sequoia.common.exceptions.driver.protocol;
021:
022: import java.io.IOException;
023: import java.sql.SQLException;
024:
025: import org.continuent.sequoia.common.stream.DriverBufferedInputStream;
026:
027: /**
028: * This class is an SQLException (typically from backend) made serializable.
029: *
030: * @author <a href="mailto:Marc.Herbert@emicnetworks.com">Marc Herbert</a>
031: * @version 1.0
032: */
033: public class BackendDriverException extends SerializableException {
034: private static final long serialVersionUID = -4044262679874226846L;
035:
036: /**
037: * @see SerializableException#SerializableException(DriverBufferedInputStream)
038: */
039: public BackendDriverException(DriverBufferedInputStream in)
040: throws IOException {
041: super (in);
042: }
043:
044: /**
045: * Converts a chain of Throwables to a new chain of SerializableException
046: * starting with a <code>BackendDriverException</code>. The returned chain
047: * has the same length. We don't use super's method but re-implement it since
048: * we want to also convert SQLException old-style chaining into a new style
049: * chain. "SyntheticSQLException-s" from
050: * {@link org.continuent.sequoia.common.exceptions.SQLExceptionFactory} also
051: * currently use old style chaining (with setNextException).
052: *
053: * @param start head of chain to convert.
054: * @see SerializableException#SerializableException(Throwable)
055: */
056: public BackendDriverException(Throwable start) {
057: super (start.getMessage(), convertNext(start)); // recursion here
058: convertStackTrace(start);
059:
060: if (start instanceof SQLException) // hopefully, else why are we here?
061: {
062: SQLException sqlE = (SQLException) start;
063: setSQLState(sqlE.getSQLState());
064: setErrorCode(sqlE.getErrorCode());
065: }
066: }
067:
068: /**
069: * Get the first cause found (new or old style), and convert it to a new
070: * BackendDriverException object (which is Serializable)
071: */
072:
073: private static SerializableException convertNext(Throwable regularEx) {
074: /*
075: * If we find that the new standard 1.4 chain is used, then we don't even
076: * look at the old SQLException chain.
077: */
078: /*
079: * We could also <em>not</em> lose this information by: adding another
080: * separated chain to this class, serialize both chains, and convert
081: * everything back to SQLExceptions on the driver side so both chains can
082: * separately be offered to the JDBC client...
083: */
084: Throwable newStyleCause = regularEx.getCause();
085: if (null != newStyleCause)
086: return new BackendDriverException(newStyleCause);
087:
088: // check legacy style chaining
089: if (regularEx instanceof SQLException) {
090: SQLException nextE = ((SQLException) regularEx)
091: .getNextException();
092: if (null != nextE)
093: return new BackendDriverException(nextE);
094: }
095:
096: // found no more link, stop condition
097: return null;
098:
099: }
100: }
|