KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > client > am > SqlException


1 /*
2
3    Derby - Class org.apache.derby.client.am.SqlException
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20 */

21
22 package org.apache.derby.client.am;
23
24 import java.sql.SQLException JavaDoc;
25 import java.util.TreeMap JavaDoc;
26
27 import org.apache.derby.iapi.services.info.JVMInfo;
28 import org.apache.derby.shared.common.i18n.MessageUtil;
29 import org.apache.derby.shared.common.error.ExceptionUtil;
30 import org.apache.derby.shared.common.reference.SQLState;
31
32
33 // The signature of the stored procedure SQLCAMessage I have come out so far is as follows:
34
// SQLCAMessage (
35
// IN SQLCode INTEGER,
36
// IN SQLErrml SMALLINT,
37
// IN SQLErrmc VARCHAR(70),
38
// IN SQLErrp CHAR(8),
39
// IN SQLErrd0 INTEGER,
40
// IN SQLErrd1 INTEGER,
41
// IN SQLErrd2 INTEGER,
42
// IN SQLErrd3 INTEGER,
43
// IN SQLErrd4 INTEGER,
44
// IN SQLErrd5 INTEGER,
45
// IN SQLWarn CHAR(11),
46
// IN SQLState CHAR(5),
47
// IN Locale CHAR(5),
48
// IN BufferSize SMALLINT,
49
// IN LineWidth SMALLINT,
50
// OUT Message VARCHAR(2400))
51
//
52
// Some issues have been identified:
53
// 1. What would be the schema name of the stored procedue SQLCAMessage?
54
// 2. What is the format and type of the Locale parameter? If there does, I would really like to know the format of the locale in order to decide the type of the Locale parameter. Even there does not either, the Locale parameter probably still needs to be kept there for future extension, and we need to figure out the format of the locale.
55
// 3. What would be the format of the output message? Is this full message text ok or do we only need the explanation message corresponding to an SQL code. This somehow matters whether we need the Buffersize and Linewidth parameters for the stored procedure.
56
// 4. What if the invocation of stored procedure failed (due to, eg, connection dropping)? In this case, we probably need to return some client-side message.
57
//
58
// Note that this class does NOT extend java.sql.SQLException. This is because
59
// in JDBC 4 there will be multiple subclasses of SQLException defined by the
60
// spec. So we can't also extend SQLException without having to create our
61
// own mirror hierarchy of subclasses.
62
//
63
// When Derby is ready to throw an exception to the application, it catches
64
// SqlException and converts it to a java.sql.SQLException by calling the
65
// method getSQLException.
66
//
67
// It is also possible that internal routines may call public methods.
68
// In these cases, it will need to wrap a java.sql.SQLException inside
69
// a Derby SqlException so that the internal method does not have to throw
70
// java.sql.SQLException. Otherwise the chain of dependencies would quickly
71
// force the majority of internal methods to throw java.sql.SQLException.
72
// You can wrap a java.sql.SQLException inside a SqlException by using
73
// the constructor <code>new SqlException(java.sql.SQLException wrapMe)</code)
74
//
75
public class SqlException extends Exception JavaDoc implements Diagnosable {
76     protected static final int DEFAULT_ERRCODE = 99999;
77     protected Sqlca sqlca_ = null; // for engine generated errors only
78
protected String JavaDoc message_ = null;
79     private String JavaDoc batchPositionLabel_; // for batched exceptions only
80
protected String JavaDoc sqlstate_ = null;
81     protected int errorcode_ = DEFAULT_ERRCODE;
82     protected String JavaDoc causeString_ = null;
83     protected SqlException nextException_;
84     protected Throwable JavaDoc throwable_;
85     
86     public static String JavaDoc CLIENT_MESSAGE_RESOURCE_NAME =
87         "org.apache.derby.loc.clientmessages";
88     
89     // Constants for message ids used in text we print out -- not used
90
// in SqlExceptions
91
public static final String JavaDoc CAUSED_BY_EXCEPTION_ID = "J106";
92     public static final String JavaDoc BATCH_POSITION_ID = "J107";
93     
94     //SQLException factory initialised with default factory
95
//It will be over written by the SQLException factory of the
96
//supported jdbc version
97
protected static SQLExceptionFactory
98             exceptionFactory = new SQLExceptionFactory ();
99     
100     /**
101      * The message utility instance we use to find messages
102      * It's primed with the name of the client message bundle so that
103      * it knows to look there if the message isn't found in the
104      * shared message bundle.
105      */

106     private static MessageUtil msgutil_;
107     
108     /**
109      * This routine provides singleton access to an instance of MessageUtil
110      * that is constructed for client messages. It is recommended to use
111      * this singleton rather than create your own instance.
112      *
113      * The only time you need this instance is if you need to directly
114      * format an internationalized message string. In most instances this
115      * is done for you when you invoke a SqlException constructor
116      *
117      * @return a singleton instance of MessageUtil configured for client
118      * messages
119      */

120     public static MessageUtil getMessageUtil() {
121         if ( msgutil_ == null ) {
122             msgutil_ = new MessageUtil(CLIENT_MESSAGE_RESOURCE_NAME);
123         }
124         
125         return msgutil_;
126     }
127
128     /**
129      * The wrapped SQLException, if one exists
130      */

131     protected SQLException JavaDoc wrappedException_;
132   
133     //-----------------constructors-----------------------------------------------
134
// New constructors that support internationalized messages
135
// The message id is wrapped inside a class so that we can distinguish
136
// between the signatures of the new constructors and the old constructors
137

138     /**
139      * Create a SqlException. This constructor is the "base" constructor;
140      * all other constructors (which take a ClientMessageId) delegate to this
141      * constructor
142      *
143      * @param logwriter
144      * Can be null, but if provided, it is used to log this exception
145      *
146      * @param msgid
147      * The message id for this message. ClientMessageId is a simple type-safe
148      * wrapper for org.apache.derby.shared.common.reference.SQLState message id
149      * strings.
150      *
151      * @param args
152      * The set of substitution arguments for the message. The Java message
153      * formatter will substitute these arguments into the internationalized
154      * strings using the substitution ({0}, {1}, etc.) markers in the string.
155      * Any object can be passed, but if you want it to be readable, make sure
156      * toString() for the object returns something useful.
157      *
158      * @param cause
159      * Can be null. Indicates the cause of this exception. If this is
160      * an instance of SqlException or java.sql.SQLException then the exception
161      * is chained into the nextException chain. Otherwise it is chained
162      * using initCause(). On JDK 1.3, since initCause() does not exist,
163      * a non-SQL exception can not be chained. Instead, the exception class
164      * and message text is appended to the message for this exception.
165      */

166     public SqlException(LogWriter logwriter,
167         ClientMessageId msgid, Object JavaDoc[] args, Throwable JavaDoc cause)
168     {
169         this(
170             logwriter,
171             cause,
172             getMessageUtil().getCompleteMessage(
173                 msgid.msgid,
174                 args),
175             ExceptionUtil.getSQLStateFromIdentifier(msgid.msgid),
176             ExceptionUtil.getSeverityFromIdentifier(msgid.msgid));
177     }
178
179     // Use the following SQLExceptions when you want to override the error
180
// code that is derived from the severity of the message id.
181
public SqlException(LogWriter logWriter, ClientMessageId msgid, Object JavaDoc[] args,
182         SqlCode sqlcode, Throwable JavaDoc t) {
183         this(logWriter, msgid, args, t);
184         this.errorcode_ = sqlcode.getCode();
185     }
186
187     public SqlException(LogWriter logWriter, ClientMessageId msgid, Object JavaDoc[] args,
188         SqlCode sqlcode) {
189         this(logWriter, msgid, args, sqlcode, (Throwable JavaDoc)null);
190     }
191         
192     public SqlException(LogWriter logWriter, ClientMessageId msgid, SqlCode sqlcode) {
193         this(logWriter, msgid, (Object JavaDoc[])null, sqlcode);
194     }
195     
196     public SqlException(LogWriter logWriter, ClientMessageId msgid, Object JavaDoc arg1,
197         SqlCode sqlcode) {
198         this(logWriter, msgid, new Object JavaDoc[] {arg1}, sqlcode);
199     }
200         
201     public SqlException(LogWriter logWriter, ClientMessageId msgid, Object JavaDoc arg1,
202         Object JavaDoc arg2, SqlCode sqlcode) {
203         this(logWriter, msgid, new Object JavaDoc[] {arg1, arg2}, sqlcode);
204     }
205  
206     // The following constructors are all wrappers around the base constructor,
207
// created to make it easy to code against them (you don't have to pass
208
// null arguments or construct object arrays). See the javadoc for the
209
// "base" constructor for an explanation of the parameters
210
public SqlException (LogWriter logwriter,
211             ClientMessageId msgid, Throwable JavaDoc cause) {
212         this (logwriter, msgid, (Object JavaDoc[])null, cause);
213     }
214     
215     public SqlException(LogWriter logwriter, ClientMessageId msgid, Object JavaDoc[] args)
216     {
217         this(logwriter, msgid, args, (Throwable JavaDoc)null);
218     }
219     
220     public SqlException (LogWriter logwriter, ClientMessageId msgid)
221     {
222         this(logwriter, msgid, (Object JavaDoc[])null);
223     }
224     
225     public SqlException(LogWriter logwriter, ClientMessageId msgid, Object JavaDoc arg1)
226     {
227         this(logwriter, msgid, new Object JavaDoc[] { arg1 });
228     }
229     
230     public SqlException(LogWriter logwriter, ClientMessageId msgid,
231             Object JavaDoc arg1, Throwable JavaDoc cause)
232     {
233         this(logwriter, msgid, new Object JavaDoc[] { arg1 }, cause);
234     }
235     
236     public SqlException(LogWriter logwriter, ClientMessageId msgid,
237         Object JavaDoc arg1, Object JavaDoc arg2, Throwable JavaDoc cause)
238     {
239         this(logwriter, msgid, new Object JavaDoc[] { arg1, arg2 }, cause);
240     }
241     
242     public SqlException(LogWriter logwriter,
243         ClientMessageId msgid, Object JavaDoc arg1, Object JavaDoc arg2)
244     {
245         this(logwriter, msgid, new Object JavaDoc[] { arg1, arg2 });
246     }
247     
248     public SqlException(LogWriter logwriter,
249         ClientMessageId msgid, Object JavaDoc arg1, Object JavaDoc arg2, Object JavaDoc arg3)
250     {
251         this(logwriter, msgid, new Object JavaDoc[] { arg1, arg2, arg3 });
252     }
253     
254     public SqlException(LogWriter logWriter, Sqlca sqlca) {
255         this.sqlca_ = sqlca;
256         if ( logWriter != null )
257         {
258             logWriter.traceDiagnosable(this);
259         }
260     }
261     
262     // Once all messages are internationalized, these methods should become
263
// private
264
protected SqlException(LogWriter logWriter, String JavaDoc reason, String JavaDoc sqlState,
265         int errorCode)
266     {
267         this(logWriter, (Throwable JavaDoc)null, reason, sqlState, errorCode);
268     }
269
270     protected SqlException(LogWriter logWriter, java.lang.Throwable JavaDoc throwable,
271         String JavaDoc reason, String JavaDoc sqlState, int errorCode ) {
272         message_ = reason;
273         sqlstate_ = sqlState;
274         errorcode_ = errorCode;
275
276         setThrowable(throwable);
277         
278         if (logWriter != null) {
279             logWriter.traceDiagnosable(this);
280         }
281         
282     }
283     
284     /**
285      * Set the cause of this exception based on its type and
286      * the current runtime version of Java
287      */

288     protected void setThrowable(Throwable JavaDoc throwable)
289     {
290         throwable_ = throwable;
291         
292         // If the throwable is a SQL exception, use nextException rather
293
// than chained exceptions
294
if ( throwable instanceof SqlException )
295         {
296             setNextException((SqlException) throwable);
297         }
298         else if ( throwable instanceof SQLException JavaDoc )
299         {
300             setNextException((SQLException JavaDoc) throwable );
301         }
302         else if ( throwable != null )
303         {
304             // Set up a string indicating the cause if the current runtime
305
// doesn't support the initCause() method. This is then used
306
// by getMessage() when it composes the message string.
307
if (JVMInfo.JDK_ID < JVMInfo.J2SE_14 )
308             {
309                 causeString_ = " " +
310                     getMessageUtil().getTextMessage(CAUSED_BY_EXCEPTION_ID) + " " +
311                     throwable.getClass() + ": " + throwable.getMessage();
312             }
313             else
314             {
315                 initCause(throwable);
316             }
317         }
318
319     }
320         
321     /**
322      * Wrap a SQLException in a SqlException. This is used by internal routines
323      * so the don't have to throw SQLException, which, through the chain of
324      * dependencies would force more and more internal routines to throw
325      * SQLException
326      */

327     public SqlException(SQLException JavaDoc wrapme)
328     {
329         wrappedException_ = wrapme;
330     }
331                 
332     
333     /**
334      * Convert this SqlException into a java.sql.SQLException
335      */

336     public SQLException JavaDoc getSQLException()
337     {
338         if ( wrappedException_ != null )
339         {
340             return wrappedException_;
341         }
342                         
343         // When we have support for JDBC 4 SQLException subclasses, this is
344
// where we decide which exception to create
345
SQLException JavaDoc sqle = exceptionFactory.getSQLException(getMessage(), getSQLState(),
346             getErrorCode());
347
348         // If we're in a runtime that supports chained exceptions, set the cause
349
// of the SQLException to be this SqlException. Otherwise the stack
350
// trace is lost.
351
if (JVMInfo.JDK_ID >= JVMInfo.J2SE_14 )
352         {
353             sqle.initCause(this);
354         }
355
356         // Set up the nextException chain
357
if ( nextException_ != null )
358         {
359             // The exception chain gets constructed automatically through
360
// the beautiful power of recursion
361
sqle.setNextException(nextException_.getSQLException());
362         }
363         
364         return sqle;
365     }
366
367     // Label an exception element in a batched update exception chain.
368
// This text will be prepended onto the exceptions message text dynamically
369
// when getMessage() is called.
370
// Called by the Agent.
371
void setBatchPositionLabel(int index) {
372         batchPositionLabel_ = getMessageUtil().getTextMessage(BATCH_POSITION_ID) +
373             index + ": ";
374     }
375
376     public Sqlca getSqlca() {
377         return sqlca_;
378     }
379
380     public java.lang.Throwable JavaDoc getThrowable() {
381         return throwable_;
382     }
383
384     public String JavaDoc getMessage() {
385         if ( wrappedException_ != null )
386         {
387             return wrappedException_.getMessage();
388         }
389         
390         if (sqlca_ != null) {
391             message_ = ((Sqlca) sqlca_).getJDBCMessage();
392         }
393         
394         if (batchPositionLabel_ != null) {
395             message_ = batchPositionLabel_ + message_;
396         }
397         
398         if ( causeString_ != null ) {
399             // Append the string indicating the cause of the exception
400
// (this happens only in JDK13 environments)
401
message_ += causeString_;
402         }
403         
404         return message_;
405     }
406
407     public String JavaDoc getSQLState() {
408         if ( wrappedException_ != null )
409         {
410             return wrappedException_.getSQLState();
411         }
412         
413         if (sqlca_ == null) {
414             return sqlstate_;
415         } else {
416             return sqlca_.getSqlState();
417         }
418     }
419
420     public int getErrorCode() {
421         if ( wrappedException_ != null )
422         {
423             return wrappedException_.getErrorCode();
424         }
425         
426         if (sqlca_ == null) {
427             return errorcode_;
428         } else {
429             return sqlca_.getSqlCode();
430         }
431     }
432
433     public SqlException getNextException()
434     {
435         if ( wrappedException_ != null )
436         {
437             return new SqlException(wrappedException_.getNextException());
438         }
439         else
440         {
441             return nextException_;
442         }
443     }
444     
445     public void setNextException(SqlException nextException)
446     {
447         if ( wrappedException_ != null )
448         {
449             wrappedException_.setNextException(nextException.getSQLException());
450         }
451         else
452         {
453             nextException_ = nextException;
454         }
455     }
456     
457     public void setNextException(SQLException JavaDoc nextException)
458     {
459         if ( wrappedException_ != null )
460         {
461             wrappedException_.setNextException(nextException);
462         }
463         else
464         {
465             // Add this exception to the end of the chain
466
SqlException theEnd = this;
467             while (theEnd.nextException_ != null) {
468                 theEnd = theEnd.nextException_;
469             }
470             theEnd.nextException_ = new SqlException(nextException);
471         }
472     }
473
474     public void printTrace(java.io.PrintWriter JavaDoc printWriter, String JavaDoc header) {
475         ExceptionFormatter.printTrace(this, printWriter, header);
476     }
477     
478     /**
479      * Helper method to construct an exception which basically says that
480      * we encountered an underlying Java exception
481      */

482     public static SqlException javaException(LogWriter logWriter, Throwable JavaDoc e) {
483         return new SqlException(logWriter,
484             new ClientMessageId (SQLState.JAVA_EXCEPTION),
485             new Object JavaDoc[] {e.getClass().getName(), e.getMessage()}, e);
486     }
487     
488     // Return a single SQLException without the "next" pointing to another SQLException.
489
// Because the "next" is a private field in java.sql.SQLException,
490
// we have to create a new SqlException in order to break the chain with "next" as null.
491
SqlException copyAsUnchainedSQLException(LogWriter logWriter) {
492         if (sqlca_ != null) {
493             return new SqlException(logWriter, sqlca_); // server error
494
} else {
495             return new SqlException(logWriter, getMessage(), getSQLState(), getErrorCode()); // client error
496
}
497     }
498     
499     /**
500      * Sets the exceptionFactory to be used for creating SQLException
501      * @param factory SQLExceptionFactory
502      */

503     public static void setExceptionFactory (SQLExceptionFactory factory) {
504         exceptionFactory = factory;
505     }
506 }
507
508 // An intermediate exception encapsulation to provide code-reuse
509
// for common ResultSet data conversion exceptions.
510

511 class ColumnTypeConversionException extends SqlException {
512     ColumnTypeConversionException(LogWriter logWriter, String JavaDoc sourceType,
513         String JavaDoc targetType) {
514         super(logWriter,
515             new ClientMessageId(SQLState.LANG_DATA_TYPE_GET_MISMATCH),
516             sourceType, targetType);
517     }
518 }
519
520 // An intermediate exception encapsulation to provide code-reuse
521
// for common CrossConverters data conversion exceptions.
522

523 class LossOfPrecisionConversionException extends SqlException {
524     LossOfPrecisionConversionException(LogWriter logWriter, String JavaDoc instance) {
525         super(logWriter, new ClientMessageId(SQLState.LOSS_OF_PRECISION_EXCEPTION),
526             instance);
527     }
528 }
529
Popular Tags