001: /*
002:
003: Derby - Class org.apache.derby.impl.jdbc.Util
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.jdbc;
023:
024: import org.apache.derby.iapi.error.StandardException;
025: import org.apache.derby.iapi.services.i18n.MessageService;
026:
027: import org.apache.derby.iapi.services.sanity.SanityManager;
028: import org.apache.derby.iapi.services.io.StoredFormatIds;
029: import org.apache.derby.iapi.types.TypeId;
030:
031: import org.apache.derby.iapi.error.ExceptionSeverity;
032:
033: import org.apache.derby.iapi.reference.SQLState;
034: import org.apache.derby.iapi.reference.MessageId;
035: import org.apache.derby.iapi.reference.JDBC30Translation;
036: import org.apache.derby.iapi.reference.JDBC40Translation;
037:
038: import java.sql.SQLException;
039: import java.sql.Types;
040: import java.io.IOException;
041: import java.io.PrintStream;
042: import java.io.PrintWriter;
043:
044: /**
045: This class understands the message protocol and looks up
046: SQLExceptions based on keys, so that the Local JDBC driver's
047: messages can be localized.
048:
049: REMIND: May want to investigate putting some of this in the protocol
050: side, for the errors that any Cloudscape JDBC driver might return.
051:
052: The ASSERT mechanism is a wrapper of the basic services,
053: to ensure that failed asserts at this level will behave
054: well in a JDBC environment.
055:
056: @author ames
057: */
058: //In the past, this class was sent on the wire to the client and because it
059: //has the message protcol stuff and also the detailed stack trace as one
060: //of it's member variable, the client.jar files was really big. To get
061: //around this problem, now we have added EmbedSQLException which is
062: //just a java sql exception with the stack trace information variable
063: //transient so it doesn't get transported to the client side and thus
064: //reducing the size of client.jar The bug for this fix was 1850. The
065: //p4 number for it will have the details of all the files impacted and
066: //the actual changes made.
067: public abstract class Util {
068:
069: private static SQLExceptionFactory exceptionFactory = new SQLExceptionFactory();
070:
071: /*
072: ** Methods of Throwable
073: */
074:
075: // class implementation
076: /**
077: * This looks up the message and sqlstate values and calls
078: * the SQLExceptionFactory method to generate
079: * the appropriate exception off of them.
080: */
081:
082: private static SQLException newEmbedSQLException(String messageId,
083: Object[] args, SQLException next, int severity, Throwable t) {
084: String message = MessageService.getCompleteMessage(messageId,
085: args);
086: return exceptionFactory.getSQLException(message, messageId,
087: next, severity, t, args);
088: }
089:
090: public static SQLException newEmbedSQLException(String messageId,
091: Object[] args, int severity) {
092: return newEmbedSQLException(messageId, args,
093: (SQLException) null, severity, (Throwable) null);
094: }
095:
096: private static SQLException newEmbedSQLException(String messageId,
097: Object[] args, int severity, Throwable t) {
098: return newEmbedSQLException(messageId, args,
099: (SQLException) null, severity, t);
100: }
101:
102: private static SQLException newEmbedSQLException(String messageId,
103: int severity) {
104: return newEmbedSQLException(messageId, (Object[]) null,
105: (SQLException) null, severity, (Throwable) null);
106: }
107:
108: // class interface
109:
110: /**
111: Mimic SanityManager.ASSERT in a JDBC-friendly way,
112: and providing system cleanup for JDBC failures.
113: We need the connection to do cleanup...
114:
115: @exception SQLException the exception
116: */
117: public static void ASSERT(EmbedConnection conn, boolean mustBeTrue,
118: String msg) throws SQLException {
119: if (SanityManager.DEBUG) {
120: try {
121: SanityManager.ASSERT(mustBeTrue, msg);
122: } catch (Throwable t) {
123: SQLException se = conn.handleException(t);
124: // get around typing constraints.
125: // it must be a Util, we wrapped it.
126: SanityManager.ASSERT(se instanceof EmbedSQLException);
127: throw (EmbedSQLException) se;
128: }
129: }
130: }
131:
132: /**
133: Mimic SanityManager.THROWASSERT in a JDBC-friendly way,
134: and providing system cleanup for JDBC failures.
135: We need the connection to do cleanup...
136: */
137: static void THROWASSERT(EmbedConnection conn, String msg)
138: throws SQLException {
139: if (SanityManager.DEBUG) {
140: try {
141: SanityManager.THROWASSERT(msg);
142: } catch (Throwable t) {
143: SQLException se = conn.handleException(t);
144: // get around typing constraints.
145: // it must be a Util, we wrapped it.
146: SanityManager.ASSERT(se instanceof EmbedSQLException);
147: throw (EmbedSQLException) se;
148: }
149: }
150: }
151:
152: /*
153: ** There is at least one static method for each message id.
154: ** Its parameters are specific to its message.
155: ** These will throw SQLException when the message repository
156: ** cannot be located.
157: ** Note that these methods call the static method newEmbedSQLException,
158: ** they don't directly do a new Util.
159: */
160:
161: /* 3 arguments */
162: static SQLException newException(String messageID, Object a1,
163: Object a2, Object a3) {
164: return newEmbedSQLException(messageID, new Object[] { a1, a2,
165: a3 }, StandardException
166: .getSeverityFromIdentifier(messageID));
167: }
168:
169: public static SQLException generateCsSQLException(String error) {
170: return newEmbedSQLException(error, StandardException
171: .getSeverityFromIdentifier(error));
172: }
173:
174: public static SQLException generateCsSQLException(String error,
175: Object arg1) {
176: return newEmbedSQLException(error, new Object[] { arg1 },
177: StandardException.getSeverityFromIdentifier(error));
178: }
179:
180: public static SQLException generateCsSQLException(String error,
181: Object arg1, Object arg2) {
182: return newEmbedSQLException(error, new Object[] { arg1, arg2 },
183: StandardException.getSeverityFromIdentifier(error));
184: }
185:
186: public static SQLException generateCsSQLException(String error,
187: Object arg1, Object arg2, Object arg3) {
188:
189: return newEmbedSQLException(error, new Object[] { arg1, arg2,
190: arg3 }, StandardException
191: .getSeverityFromIdentifier(error));
192: }
193:
194: static SQLException generateCsSQLException(String error,
195: Object arg1, Throwable t) {
196: return newEmbedSQLException(error, new Object[] { arg1 },
197: StandardException.getSeverityFromIdentifier(error), t);
198: }
199:
200: public static SQLException generateCsSQLException(
201: StandardException se) {
202: return exceptionFactory.getSQLException(se.getMessage(), se
203: .getMessageId(), (SQLException) null, se.getSeverity(),
204: se, se.getArguments());
205: }
206:
207: public static SQLException noCurrentConnection() {
208: return newEmbedSQLException(
209: SQLState.NO_CURRENT_CONNECTION,
210: StandardException
211: .getSeverityFromIdentifier(SQLState.NO_CURRENT_CONNECTION));
212: }
213:
214: public static SQLException javaException(Throwable t) {
215: String name, msg;
216:
217: msg = t.getMessage();
218: if (msg == null)
219: msg = "";
220: name = t.getClass().getName();
221: return newEmbedSQLException(SQLState.JAVA_EXCEPTION,
222: new Object[] { name, msg },
223: ExceptionSeverity.NO_APPLICABLE_SEVERITY, t);
224: }
225:
226: public static SQLException notImplemented() {
227:
228: return notImplemented(MessageService
229: .getTextMessage(MessageId.CONN_NO_DETAILS));
230: }
231:
232: public static SQLException notImplemented(String feature) {
233:
234: return newEmbedSQLException(
235: SQLState.NOT_IMPLEMENTED,
236: new Object[] { feature },
237: StandardException
238: .getSeverityFromIdentifier(SQLState.NOT_IMPLEMENTED));
239: }
240:
241: static SQLException setStreamFailure(IOException e) {
242: String msg;
243:
244: msg = e.getMessage();
245: if (msg == null)
246: msg = e.getClass().getName();
247: return newEmbedSQLException(
248: SQLState.SET_STREAM_FAILURE,
249: new Object[] { msg },
250: StandardException
251: .getSeverityFromIdentifier(SQLState.SET_STREAM_FAILURE));
252: }
253:
254: static SQLException typeMisMatch(int targetSQLType) {
255: return newEmbedSQLException(
256: SQLState.TYPE_MISMATCH,
257: new Object[] { typeName(targetSQLType) },
258: StandardException
259: .getSeverityFromIdentifier(SQLState.TYPE_MISMATCH));
260: }
261:
262: /**
263: * this method is called to replace the exception factory to be
264: * used to generate the SQLException or the subclass
265: */
266:
267: public static void setExceptionFactory(SQLExceptionFactory factory) {
268: exceptionFactory = factory;
269: }
270:
271: /**
272: * Get the exception factory specific to the version of JDBC which
273: * we are running.
274: */
275: public static SQLExceptionFactory getExceptionFactory() {
276: return exceptionFactory;
277: }
278:
279: public static String typeName(int jdbcType) {
280: switch (jdbcType) {
281: case Types.ARRAY:
282: return TypeId.ARRAY_NAME;
283: case Types.BIT:
284: return TypeId.BIT_NAME;
285: case JDBC30Translation.SQL_TYPES_BOOLEAN:
286: return TypeId.BOOLEAN_NAME;
287: case JDBC30Translation.DATALINK:
288: return TypeId.DATALINK_NAME;
289: case Types.TINYINT:
290: return TypeId.TINYINT_NAME;
291: case Types.SMALLINT:
292: return TypeId.SMALLINT_NAME;
293: case Types.INTEGER:
294: return TypeId.INTEGER_NAME;
295: case Types.BIGINT:
296: return TypeId.LONGINT_NAME;
297:
298: case Types.FLOAT:
299: return TypeId.FLOAT_NAME;
300: case Types.REAL:
301: return TypeId.REAL_NAME;
302: case Types.DOUBLE:
303: return TypeId.DOUBLE_NAME;
304:
305: case Types.NUMERIC:
306: return TypeId.NUMERIC_NAME;
307: case Types.DECIMAL:
308: return TypeId.DECIMAL_NAME;
309:
310: case Types.CHAR:
311: return TypeId.CHAR_NAME;
312: case JDBC40Translation.NCHAR:
313: return TypeId.NATIONAL_CHAR_NAME;
314: case Types.VARCHAR:
315: return TypeId.VARCHAR_NAME;
316: case JDBC40Translation.NVARCHAR:
317: return TypeId.NATIONAL_VARCHAR_NAME;
318: case Types.LONGVARCHAR:
319: return "LONGVARCHAR";
320: case JDBC40Translation.LONGNVARCHAR:
321: return TypeId.NATIONAL_LONGVARCHAR_NAME;
322: case Types.CLOB:
323: return TypeId.CLOB_NAME;
324: case JDBC40Translation.NCLOB:
325: return TypeId.NCLOB_NAME;
326:
327: case Types.DATE:
328: return TypeId.DATE_NAME;
329: case Types.TIME:
330: return TypeId.TIME_NAME;
331: case Types.TIMESTAMP:
332: return TypeId.TIMESTAMP_NAME;
333:
334: case Types.BINARY:
335: return TypeId.BINARY_NAME;
336: case Types.VARBINARY:
337: return TypeId.VARBINARY_NAME;
338: case Types.LONGVARBINARY:
339: return TypeId.LONGVARBINARY_NAME;
340: case Types.BLOB:
341: return TypeId.BLOB_NAME;
342:
343: case Types.OTHER:
344: return "OTHER";
345: case Types.JAVA_OBJECT:
346: return "Types.JAVA_OBJECT";
347: case Types.REF:
348: return TypeId.REF_NAME;
349: case JDBC40Translation.ROWID:
350: return TypeId.ROWID_NAME;
351: case Types.STRUCT:
352: return TypeId.STRUCT_NAME;
353: case StoredFormatIds.XML_TYPE_ID:
354: return TypeId.XML_NAME;
355: case JDBC40Translation.SQLXML:
356: return TypeId.SQLXML_NAME;
357: default:
358: return String.valueOf(jdbcType);
359: }
360: }
361: }
|