1 | /* |
2 | |
3 | Derby - Class org.apache.derby.impl.jdbc.Util |
4 | |
5 | Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.impl.jdbc; |
22 | |
23 | import org.apache.derby.iapi.error.StandardException; |
24 | import org.apache.derby.iapi.services.i18n.MessageService; |
25 | |
26 | import org.apache.derby.iapi.services.sanity.SanityManager; |
27 | import org.apache.derby.iapi.services.io.StoredFormatIds; |
28 | import org.apache.derby.iapi.types.TypeId; |
29 | |
30 | import org.apache.derby.iapi.error.ExceptionSeverity; |
31 | |
32 | import org.apache.derby.iapi.reference.SQLState; |
33 | import org.apache.derby.iapi.reference.MessageId; |
34 | import org.apache.derby.iapi.reference.JDBC30Translation; |
35 | |
36 | import java.sql.SQLException; |
37 | import java.sql.Types; |
38 | import java.io.IOException; |
39 | import java.io.PrintStream; |
40 | import java.io.PrintWriter; |
41 | |
42 | /** |
43 | This class understands the message protocol and looks up |
44 | SQLExceptions based on keys, so that the Local JDBC driver's |
45 | messages can be localized. |
46 | |
47 | REMIND: May want to investigate putting some of this in the protocol |
48 | side, for the errors that any Cloudscape JDBC driver might return. |
49 | |
50 | The ASSERT mechanism is a wrapper of the basic services, |
51 | to ensure that failed asserts at this level will behave |
52 | well in a JDBC environment. |
53 | |
54 | @author ames |
55 | */ |
56 | //In the past, this class was sent on the wire to the client and because it |
57 | //has the message protcol stuff and also the detailed stack trace as one |
58 | //of it's member variable, the client.jar files was really big. To get |
59 | //around this problem, now we have added EmbedSQLException which is |
60 | //just a java sql exception with the stack trace information variable |
61 | //transient so it doesn't get transported to the client side and thus |
62 | //reducing the size of client.jar The bug for this fix was 1850. The |
63 | //p4 number for it will have the details of all the files impacted and |
64 | //the actual changes made. |
65 | public abstract class Util { |
66 | |
67 | |
68 | private static SQLExceptionFactory exceptionFactory = |
69 | new SQLExceptionFactory (); |
70 | |
71 | /* |
72 | ** Methods of Throwable |
73 | */ |
74 | |
75 | // class implementation |
76 | |
77 | /** |
78 | * This looks up the message and sqlstate values and calls |
79 | * the SQLExceptionFactory method to generate |
80 | * the appropriate exception off of them. |
81 | */ |
82 | |
83 | private static SQLException newEmbedSQLException(String messageId, |
84 | Object[] args, SQLException next, int severity, Throwable t) { |
85 | String message = MessageService.getCompleteMessage |
86 | (messageId, args); |
87 | return exceptionFactory.getSQLException ( |
88 | message, messageId, next, severity, t, args); |
89 | } |
90 | |
91 | public static SQLException newEmbedSQLException(String messageId, |
92 | Object[] args, int severity) { |
93 | return newEmbedSQLException(messageId, args, (SQLException) null, severity, (Throwable) null); |
94 | } |
95 | |
96 | private static SQLException newEmbedSQLException(String messageId, |
97 | Object[] args, int severity, Throwable t) { |
98 | return newEmbedSQLException(messageId,args, (SQLException) null, severity, t); |
99 | } |
100 | |
101 | private static SQLException newEmbedSQLException( |
102 | String messageId, int severity) { |
103 | return newEmbedSQLException(messageId, (Object[]) null, (SQLException) null, severity, (Throwable) null); |
104 | } |
105 | |
106 | // class interface |
107 | |
108 | |
109 | /** |
110 | Mimic SanityManager.ASSERT in a JDBC-friendly way, |
111 | and providing system cleanup for JDBC failures. |
112 | We need the connection to do cleanup... |
113 | |
114 | @exception SQLException the exception |
115 | */ |
116 | public static void ASSERT(EmbedConnection conn, boolean mustBeTrue, String msg) throws SQLException { |
117 | if (SanityManager.DEBUG) { |
118 | try { |
119 | SanityManager.ASSERT(mustBeTrue, msg); |
120 | } catch (Throwable t) { |
121 | SQLException se = conn.handleException(t); |
122 | // get around typing constraints. |
123 | // it must be a Util, we wrapped it. |
124 | SanityManager.ASSERT(se instanceof EmbedSQLException); |
125 | throw (EmbedSQLException)se; |
126 | } |
127 | } |
128 | } |
129 | |
130 | /** |
131 | Mimic SanityManager.THROWASSERT in a JDBC-friendly way, |
132 | and providing system cleanup for JDBC failures. |
133 | We need the connection to do cleanup... |
134 | */ |
135 | static void THROWASSERT(EmbedConnection conn, String msg) throws SQLException { |
136 | if (SanityManager.DEBUG) { |
137 | try { |
138 | SanityManager.THROWASSERT(msg); |
139 | } catch (Throwable t) { |
140 | SQLException se = conn.handleException(t); |
141 | // get around typing constraints. |
142 | // it must be a Util, we wrapped it. |
143 | SanityManager.ASSERT(se instanceof EmbedSQLException); |
144 | throw (EmbedSQLException)se; |
145 | } |
146 | } |
147 | } |
148 | |
149 | /* |
150 | ** There is at least one static method for each message id. |
151 | ** Its parameters are specific to its message. |
152 | ** These will throw SQLException when the message repository |
153 | ** cannot be located. |
154 | ** Note that these methods call the static method newEmbedSQLException, |
155 | ** they don't directly do a new Util. |
156 | */ |
157 | |
158 | /* 3 arguments */ |
159 | static SQLException newException(String messageID, Object a1, |
160 | Object a2, Object a3) { |
161 | return newEmbedSQLException(messageID, new Object[] {a1, a2, a3}, |
162 | StandardException.getSeverityFromIdentifier(messageID)); |
163 | } |
164 | |
165 | |
166 | public static SQLException generateCsSQLException(String error) { |
167 | return newEmbedSQLException(error, |
168 | StandardException.getSeverityFromIdentifier(error)); |
169 | } |
170 | |
171 | public static SQLException generateCsSQLException(String error, Object arg1) { |
172 | return newEmbedSQLException(error, |
173 | new Object[] {arg1}, |
174 | StandardException.getSeverityFromIdentifier(error)); |
175 | } |
176 | |
177 | public static SQLException generateCsSQLException( |
178 | String error, Object arg1, Object arg2){ |
179 | return newEmbedSQLException(error, |
180 | new Object[] {arg1, arg2}, |
181 | StandardException.getSeverityFromIdentifier(error)); |
182 | } |
183 | |
184 | public static SQLException generateCsSQLException( |
185 | String error, Object arg1, Object arg2, Object arg3) { |
186 | |
187 | return newEmbedSQLException(error, |
188 | new Object[] {arg1, arg2, arg3}, |
189 | StandardException.getSeverityFromIdentifier(error)); |
190 | } |
191 | |
192 | |
193 | static SQLException generateCsSQLException( |
194 | String error, Object arg1, Throwable t) { |
195 | return newEmbedSQLException(error, |
196 | new Object[] {arg1}, |
197 | StandardException.getSeverityFromIdentifier(error), t); |
198 | } |
199 | |
200 | public static SQLException generateCsSQLException(StandardException se) { |
201 | return exceptionFactory.getSQLException( |
202 | se.getMessage(), se.getMessageId(), (SQLException) null, |
203 | se.getSeverity(), se, se.getArguments()); |
204 | } |
205 | |
206 | public static SQLException noCurrentConnection() { |
207 | return newEmbedSQLException(SQLState.NO_CURRENT_CONNECTION, |
208 | StandardException.getSeverityFromIdentifier(SQLState.NO_CURRENT_CONNECTION)); |
209 | } |
210 | |
211 | public static SQLException javaException(Throwable t) { |
212 | String name, msg; |
213 | |
214 | msg = t.getMessage(); |
215 | if (msg == null) msg = ""; |
216 | name = t.getClass().getName(); |
217 | return newEmbedSQLException(SQLState.JAVA_EXCEPTION, |
218 | new Object[] {name, msg}, ExceptionSeverity.NO_APPLICABLE_SEVERITY, t); |
219 | } |
220 | |
221 | |
222 | public static SQLException notImplemented() { |
223 | |
224 | return notImplemented( MessageService.getTextMessage(MessageId.CONN_NO_DETAILS) ); |
225 | } |
226 | |
227 | public static SQLException notImplemented(String feature) { |
228 | |
229 | return newEmbedSQLException(SQLState.NOT_IMPLEMENTED, |
230 | new Object[] {feature}, |
231 | StandardException.getSeverityFromIdentifier(SQLState.NOT_IMPLEMENTED)); |
232 | } |
233 | |
234 | static SQLException setStreamFailure(IOException e) { |
235 | String msg; |
236 | |
237 | msg = e.getMessage(); |
238 | if (msg == null) |
239 | msg = e.getClass().getName(); |
240 | return newEmbedSQLException(SQLState.SET_STREAM_FAILURE, |
241 | new Object[] {msg}, |
242 | StandardException.getSeverityFromIdentifier(SQLState.SET_STREAM_FAILURE)); |
243 | } |
244 | |
245 | static SQLException typeMisMatch(int targetSQLType) { |
246 | return newEmbedSQLException(SQLState.TYPE_MISMATCH, |
247 | new Object[] {typeName(targetSQLType)}, |
248 | StandardException.getSeverityFromIdentifier(SQLState.TYPE_MISMATCH)); |
249 | } |
250 | |
251 | /** |
252 | * this method is called to replace the exception factory to be |
253 | * used to generate the SQLException or the subclass |
254 | */ |
255 | |
256 | public static void setExceptionFactory (SQLExceptionFactory factory) { |
257 | exceptionFactory = factory; |
258 | } |
259 | |
260 | /** |
261 | * Get the exception factory specific to the version of JDBC which |
262 | * we are running. |
263 | */ |
264 | public static SQLExceptionFactory getExceptionFactory() { return exceptionFactory; } |
265 | |
266 | public static String typeName(int jdbcType) { |
267 | switch (jdbcType) { |
268 | case Types.BIT : return TypeId.BIT_NAME; |
269 | case JDBC30Translation.SQL_TYPES_BOOLEAN : return TypeId.BOOLEAN_NAME; |
270 | case Types.TINYINT : return TypeId.TINYINT_NAME; |
271 | case Types.SMALLINT : return TypeId.SMALLINT_NAME; |
272 | case Types.INTEGER : return TypeId.INTEGER_NAME; |
273 | case Types.BIGINT : return TypeId.LONGINT_NAME; |
274 | |
275 | case Types.FLOAT : return TypeId.FLOAT_NAME; |
276 | case Types.REAL : return TypeId.REAL_NAME; |
277 | case Types.DOUBLE : return TypeId.DOUBLE_NAME; |
278 | |
279 | case Types.NUMERIC : return TypeId.NUMERIC_NAME; |
280 | case Types.DECIMAL : return TypeId.DECIMAL_NAME; |
281 | |
282 | case Types.CHAR : return TypeId.CHAR_NAME; |
283 | case Types.VARCHAR : return TypeId.VARCHAR_NAME; |
284 | case Types.LONGVARCHAR : return "LONGVARCHAR"; |
285 | case Types.CLOB : return TypeId.CLOB_NAME; |
286 | |
287 | case Types.DATE : return TypeId.DATE_NAME; |
288 | case Types.TIME : return TypeId.TIME_NAME; |
289 | case Types.TIMESTAMP : return TypeId.TIMESTAMP_NAME; |
290 | |
291 | case Types.BINARY : return TypeId.BINARY_NAME; |
292 | case Types.VARBINARY : return TypeId.VARBINARY_NAME; |
293 | case Types.LONGVARBINARY : return TypeId.LONGVARBINARY_NAME; |
294 | case Types.BLOB : return TypeId.BLOB_NAME; |
295 | |
296 | case Types.OTHER : return "OTHER"; |
297 | case Types.JAVA_OBJECT : return "Types.JAVA_OBJECT"; |
298 | case StoredFormatIds.XML_TYPE_ID : return TypeId.XML_NAME; |
299 | default : return String.valueOf(jdbcType); |
300 | } |
301 | } |
302 | } |