KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.client.am.Sqlca
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 org.apache.derby.shared.common.reference.SQLState;
25 import org.apache.derby.client.net.Typdef;
26
27 public abstract class Sqlca {
28     transient protected Connection connection_;
29     SqlException exceptionThrownOnStoredProcInvocation_;
30     boolean messageTextRetrievedContainsTokensOnly_ = true;
31
32     // data corresponding to SQLCA fields
33
protected int sqlCode_; // SQLCODE
34
private String JavaDoc sqlErrmc_; // A string with all error tokens delimited by sqlErrmcDelimiter
35
protected String JavaDoc[] sqlErrmcTokens_; // A string array with each element
36
// contain an error token
37
protected String JavaDoc sqlErrp_; // function name issuing error
38
protected int[] sqlErrd_; // 6 diagnostic Information
39
protected char[] sqlWarn_; // 11 warning Flags
40
protected String JavaDoc sqlState_; // SQLSTATE
41

42     // raw sqlca data fields before unicode conversion
43
protected byte[] sqlErrmcBytes_;
44     protected byte[] sqlErrpBytes_;
45     protected byte[] sqlWarnBytes_;
46     
47     protected int sqlErrmcCcsid_;
48     protected boolean containsSqlcax_ = true;
49     protected long rowsetRowCount_;
50
51     //public static final String sqlErrmcDelimiter = "\u00FF";
52
private static final String JavaDoc sqlErrmcDelimiter__ = ";";
53
54     // JDK stack trace calls e.getMessage(), so we must set some state on the sqlca that says return tokens only.
55
private boolean returnTokensOnlyInMessageText_ = false;
56
57     transient private final Agent agent_;
58
59     private String JavaDoc cachedMessage;
60
61     protected Sqlca(org.apache.derby.client.am.Connection connection) {
62         connection_ = connection;
63         agent_ = connection_ != null ? connection_.agent_ : null;
64     }
65
66     void returnTokensOnlyInMessageText(boolean returnTokensOnlyInMessageText) {
67         returnTokensOnlyInMessageText_ = returnTokensOnlyInMessageText;
68     }
69
70     synchronized public int getSqlCode() {
71         return sqlCode_;
72     }
73
74     synchronized public String JavaDoc getSqlErrmc() {
75         if (sqlErrmc_ != null) {
76             return sqlErrmc_;
77         }
78
79         // sqlErrmc string is dependent on sqlErrmcTokens array having been built
80
if (sqlErrmcTokens_ == null) {
81             getSqlErrmcTokens();
82         }
83
84         // sqlErrmc will be build only if sqlErrmcTokens has been build.
85
// Otherwise, a null string will be returned.
86
if (sqlErrmcTokens_ == null) {
87             return null;
88         }
89
90         // create 0-length String if no tokens
91
if (sqlErrmcTokens_.length == 0) {
92             sqlErrmc_ = "";
93             return sqlErrmc_;
94         }
95
96         // concatenate tokens with sqlErrmcDelimiter delimiters into one String
97
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
98         int indx;
99         for (indx = 0; indx < sqlErrmcTokens_.length - 1; indx++) {
100             buffer.append(sqlErrmcTokens_[indx]);
101             buffer.append(sqlErrmcDelimiter__);
102         }
103         // add the last token
104
buffer.append(sqlErrmcTokens_[indx]);
105
106         // save as a string
107
sqlErrmc_ = buffer.toString();
108         return sqlErrmc_;
109     }
110
111     synchronized public String JavaDoc[] getSqlErrmcTokens() {
112         if (sqlErrmcTokens_ != null) {
113             return sqlErrmcTokens_;
114         }
115
116         // processSqlErrmcTokens handles null sqlErrmcBytes_ case
117
sqlErrmcTokens_ = processSqlErrmcTokens(sqlErrmcBytes_);
118         return sqlErrmcTokens_;
119     }
120
121     synchronized public String JavaDoc getSqlErrp() {
122         if (sqlErrp_ != null) {
123             return sqlErrp_;
124         }
125
126         if (sqlErrpBytes_ == null) {
127             return null;
128         }
129
130         try {
131             sqlErrp_ = bytes2String(sqlErrpBytes_,
132                     0,
133                     sqlErrpBytes_.length);
134             return sqlErrp_;
135         } catch (java.io.UnsupportedEncodingException JavaDoc e) {
136             // leave sqlErrp as null.
137
return null;
138         }
139     }
140
141     public int[] getSqlErrd() {
142         if (sqlErrd_ != null) {
143             return sqlErrd_;
144         }
145
146         sqlErrd_ = new int[6]; // create an int array.
147
return sqlErrd_;
148     }
149
150     synchronized public char[] getSqlWarn() {
151         if (sqlWarn_ != null) {
152             return sqlWarn_;
153         }
154
155         try {
156             if (sqlWarnBytes_ == null) {
157                 sqlWarn_ = new char[]{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; // 11 blank.
158
} else {
159                 sqlWarn_ = bytes2String(sqlWarnBytes_, 0, sqlWarnBytes_.length).toCharArray();
160             }
161             return sqlWarn_;
162         } catch (java.io.UnsupportedEncodingException JavaDoc e) {
163             sqlWarn_ = new char[]{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; // 11 blank.
164
return sqlWarn_;
165         }
166     }
167
168     synchronized public String JavaDoc getSqlState() {
169         return sqlState_;
170     }
171
172     // Gets the formatted message, can throw an exception.
173
synchronized public String JavaDoc getMessage() throws SqlException {
174         // should this be traced to see if we are calling a stored proc?
175
if (cachedMessage != null) {
176             return cachedMessage;
177         }
178
179         if (connection_ == null || connection_.isClosedX() || returnTokensOnlyInMessageText_) {
180             return getUnformattedMessage();
181         }
182
183         CallableStatement cs = null;
184         synchronized (connection_) {
185             try {
186                 cs = connection_.prepareMessageProc("call SYSIBM.SQLCAMESSAGE(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
187
188                 // SQLCode: SQL return code.
189
cs.setIntX(1, getSqlCode());
190                 // SQLErrml: Length of SQL error message tokens.
191
cs.setShortX(2, (short) ((getSqlErrmc() != null) ? getSqlErrmc().length() : 0));
192                 // SQLErrmc: SQL error message tokens as a String (delimited by semicolon ";").
193
cs.setStringX(3, getSqlErrmc());
194                 // SQLErrp: Product signature.
195
cs.setStringX(4, getSqlErrp());
196                 // SQLErrd: SQL internal error code.
197
cs.setIntX(5, getSqlErrd()[0]);
198                 cs.setIntX(6, getSqlErrd()[1]);
199                 cs.setIntX(7, getSqlErrd()[2]);
200                 cs.setIntX(8, getSqlErrd()[3]);
201                 cs.setIntX(9, getSqlErrd()[4]);
202                 cs.setIntX(10, getSqlErrd()[5]);
203                 // SQLWarn: SQL warning flags.
204
cs.setStringX(11, new String JavaDoc(getSqlWarn()));
205                 // SQLState: standard SQL state.
206
cs.setStringX(12, getSqlState());
207                 // MessageFileName: Not used by our driver, so set to null.
208
cs.setStringX(13, null);
209                 // Locale: language preference requested for the return error message.
210
cs.setStringX(14, java.util.Locale.getDefault().toString());
211                 // server could return a locale different from what we requested
212
cs.registerOutParameterX(14, java.sql.Types.VARCHAR);
213                 // Message: error message returned from SQLCAMessage stored procedure.
214
cs.registerOutParameterX(15, java.sql.Types.LONGVARCHAR);
215                 // RCode: return code from SQLCAMessage stored procedure.
216
cs.registerOutParameterX(16, java.sql.Types.INTEGER);
217                 cs.executeX();
218
219                 if (cs.getIntX(16) == 0) {
220                     // Return the message text.
221
messageTextRetrievedContainsTokensOnly_ = false;
222                     String JavaDoc message = cs.getStringX(15);
223                     cachedMessage = message;
224                     return message;
225                 } else {
226                     // Stored procedure can't return a valid message text, so we return
227
// unformated exception
228
return getUnformattedMessage();
229                 }
230             } finally {
231                 if (cs != null) {
232                     try {
233                         cs.closeX();
234                     } catch (SqlException doNothing) {
235                     }
236                 }
237             }
238         }
239     }
240
241     // May or may not get the formatted message depending upon datasource directives. cannot throw exeption.
242
public synchronized String JavaDoc getJDBCMessage() {
243         // The transient connection_ member will only be null if the Sqlca has been deserialized
244
if (connection_ != null && connection_.retrieveMessageText_) {
245             try {
246                 return getMessage();
247             } catch (SqlException e) {
248                 // Invocation of stored procedure fails, so we return error message tokens directly.
249
exceptionThrownOnStoredProcInvocation_ = e;
250                 chainDeferredExceptionsToAgentOrAsConnectionWarnings((SqlException) e);
251                 return getUnformattedMessage();
252             }
253         } else {
254             return getUnformattedMessage();
255         }
256     }
257
258     private String JavaDoc getUnformattedMessage() {
259         return "DERBY SQL error: SQLCODE: " + getSqlCode() + ", SQLSTATE: " + getSqlState() + ", SQLERRMC: " + getSqlErrmc();
260     }
261
262     private void chainDeferredExceptionsToAgentOrAsConnectionWarnings(SqlException e) {
263         SqlException current = e;
264         while (current != null) {
265             SqlException next = (SqlException) current.getNextException();
266             current = current.copyAsUnchainedSQLException(agent_.logWriter_);
267             if (current.getErrorCode() == -440) {
268                 SqlWarning warningForStoredProcFailure = new SqlWarning(agent_.logWriter_,
269                     new ClientMessageId(SQLState.UNABLE_TO_OBTAIN_MESSAGE_TEXT_FROM_SERVER));
270                 warningForStoredProcFailure.setNextException(current.getSQLException());
271                 connection_.accumulate440WarningForMessageProcFailure(warningForStoredProcFailure);
272             } else if (current.getErrorCode() == -444) {
273                 SqlWarning warningForStoredProcFailure = new SqlWarning(agent_.logWriter_,
274                     new ClientMessageId(SQLState.UNABLE_TO_OBTAIN_MESSAGE_TEXT_FROM_SERVER));
275                 warningForStoredProcFailure.setNextException(current.getSQLException());
276                 connection_.accumulate444WarningForMessageProcFailure(warningForStoredProcFailure);
277             } else {
278                 agent_.accumulateDeferredException(current);
279             }
280             current = next;
281         }
282     }
283
284     public boolean includesSqlCode(int[] codes) {
285         for (int i = 0; i < codes.length; i++) {
286             if (codes[i] == getSqlCode()) {
287                 return true;
288             }
289         }
290         return false;
291     }
292     // ------------------- helper methods ----------------------------------------
293

294     private String JavaDoc[] processSqlErrmcTokens(byte[] tokenBytes) {
295         if (tokenBytes == null) {
296             return null;
297         }
298
299         // create 0-length String tokens array if tokenBytes is 0-length
300
int length = tokenBytes.length;
301         if (length == 0) {
302             return new String JavaDoc[0];
303         }
304
305         try {
306             // tokenize and convert tokenBytes
307
java.io.ByteArrayOutputStream JavaDoc buffer = new java.io.ByteArrayOutputStream JavaDoc();
308             java.util.LinkedList JavaDoc tokens = new java.util.LinkedList JavaDoc();
309
310             // parse the error message tokens
311
for (int index = 0; index < length - 1; index++) {
312
313                 // non-delimiter - continue to write into buffer
314
if (tokenBytes[index] != -1) // -1 is the delimiter '\xFF'
315
{
316                     buffer.write(tokenBytes[index]);
317                 }
318
319                 // delimiter - convert current token and add to list
320
else {
321                     tokens.add(bytes2String(buffer.toByteArray(), 0, buffer.size()));
322                     buffer.reset();
323                 }
324             }
325
326             int lastIndex = length - 1;
327             // check for last byte not being a delimiter, i.e. part of last token
328
if (tokenBytes[lastIndex] != -1) {
329                 // write the last byte
330
buffer.write(tokenBytes[lastIndex]);
331                 // convert the last token and add to list
332
tokens.add(bytes2String(buffer.toByteArray(), 0, buffer.size()));
333             }
334
335             // last byte is delimiter implying an empty String for last token
336
else {
337                 // convert current token, if one exists, and add to list
338
if (lastIndex != 0) {
339                     tokens.add(bytes2String(buffer.toByteArray(), 0, buffer.size()));
340                 }
341                 // last token is an empty String
342
tokens.add("");
343             }
344
345             // create the String array and fill it with tokens.
346
String JavaDoc[] tokenStrings = new String JavaDoc[tokens.size()];
347
348             java.util.Iterator JavaDoc iterator = tokens.iterator();
349             for (int i = 0; iterator.hasNext(); i++) {
350                 tokenStrings[i] = (String JavaDoc) iterator.next();
351             }
352
353             return tokenStrings;
354         } catch (java.io.UnsupportedEncodingException JavaDoc e) {
355             return null;
356         }
357     }
358
359     protected String JavaDoc bytes2String(byte[] bytes, int offset, int length)
360             throws java.io.UnsupportedEncodingException JavaDoc {
361         // Network server uses utf8 encoding
362
return new String JavaDoc(bytes, offset, length, Typdef.UTF8ENCODING);
363     }
364
365     public int getUpdateCount() {
366         if (sqlErrd_ == null) {
367             return 0;
368         }
369         return sqlErrd_[2];
370     }
371
372     public long getRowCount() throws org.apache.derby.client.am.DisconnectException {
373         return ((long) sqlErrd_[0] << 32) + sqlErrd_[1];
374     }
375
376     public void setContainsSqlcax(boolean containsSqlcax) {
377         containsSqlcax_ = containsSqlcax;
378     }
379
380     public boolean containsSqlcax() {
381         return containsSqlcax_;
382     }
383
384     public void resetRowsetSqlca(org.apache.derby.client.am.Connection connection,
385                                  int sqlCode,
386                                  String JavaDoc sqlState,
387                                  byte[] sqlErrpBytes) {
388         connection_ = connection;
389         sqlCode_ = sqlCode;
390         sqlState_ = sqlState;
391         sqlErrpBytes_ = sqlErrpBytes;
392     }
393
394     public void setRowsetRowCount(long rowCount) {
395         rowsetRowCount_ = rowCount;
396     }
397
398     public long getRowsetRowCount() {
399         return rowsetRowCount_;
400     }
401 }
402
403
Popular Tags