1 | /* |
2 | |
3 | Derby - Class org.apache.derby.client.net.NetConnection |
4 | |
5 | Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where 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 | package org.apache.derby.client.net; |
21 | |
22 | import java.sql.SQLException; |
23 | import org.apache.derby.client.am.CallableStatement; |
24 | import org.apache.derby.client.am.DatabaseMetaData; |
25 | import org.apache.derby.client.am.DisconnectException; |
26 | import org.apache.derby.client.am.EncryptionManager; |
27 | import org.apache.derby.client.am.PreparedStatement; |
28 | import org.apache.derby.client.am.ProductLevel; |
29 | import org.apache.derby.client.am.SqlException; |
30 | import org.apache.derby.client.am.ClientMessageId; |
31 | import org.apache.derby.shared.common.reference.MessageId; |
32 | import org.apache.derby.shared.common.i18n.MessageUtil; |
33 | import org.apache.derby.client.am.Statement; |
34 | import org.apache.derby.client.am.Utils; |
35 | import org.apache.derby.jdbc.ClientBaseDataSource; |
36 | import org.apache.derby.jdbc.ClientDataSource; |
37 | import org.apache.derby.jdbc.ClientDriver; |
38 | import org.apache.derby.client.ClientPooledConnection; |
39 | |
40 | import org.apache.derby.shared.common.reference.SQLState; |
41 | |
42 | public class NetConnection extends org.apache.derby.client.am.Connection { |
43 | |
44 | // Use this to get internationalized strings... |
45 | protected static MessageUtil msgutil = SqlException.getMessageUtil(); |
46 | |
47 | protected NetAgent netAgent_; |
48 | //contains a reference to the PooledConnection from which this created |
49 | //It then passes this reference to the PreparedStatement created from it |
50 | //The PreparedStatement then uses this to pass the close and the error |
51 | //occurred conditions back to the PooledConnection which can then throw the |
52 | //appropriate events. |
53 | protected ClientPooledConnection pooledConnection_ = null; |
54 | |
55 | |
56 | // For XA Transaction |
57 | protected int pendingEndXACallinfoOffset_ = -1; |
58 | |
59 | |
60 | // byte[] to save the connect flows for connection reset |
61 | protected byte[] cachedConnectBytes_ = null; |
62 | protected boolean wroteConnectFromCache_ = false; |
63 | //-----------------------------state------------------------------------------ |
64 | |
65 | // these variables store the manager levels for the connection. |
66 | // they are initialized to the highest value which this driver supports |
67 | // at the current time. theses intial values should be increased when |
68 | // new manager level support is added to this driver. these initial values |
69 | // are sent to the server in the excsat command. the server will return a |
70 | // set of values and these will be parsed out by parseExcsatrd and parseMgrlvlls. |
71 | // during this parsing, these instance variable values will be reset to the negotiated |
72 | // levels for the connection. these values may be less than the |
73 | // values origionally set here at constructor time. it is these new values |
74 | // (following the parse) which are the levels for the connection. after |
75 | // a successful excsat command, these values can be checked to see |
76 | // what protocol is supported by this particular connection. |
77 | // if support for a new manager class is added, the buildExcsat and parseMgrlvlls |
78 | // methods will need to be changed to accomodate sending and receiving the new class. |
79 | protected int targetAgent_ = NetConfiguration.MGRLVL_7; //01292003jev monitoring |
80 | protected int targetCmntcpip_ = NetConfiguration.MGRLVL_5; |
81 | protected int targetRdb_ = NetConfiguration.MGRLVL_7; |
82 | public int targetSecmgr_ = NetConfiguration.MGRLVL_7; |
83 | protected int targetCmnappc_ = NetConfiguration.MGRLVL_NA; //NA since currently not used by net |
84 | protected int targetXamgr_ = NetConfiguration.MGRLVL_7; |
85 | protected int targetSyncptmgr_ = NetConfiguration.MGRLVL_NA; |
86 | protected int targetRsyncmgr_ = NetConfiguration.MGRLVL_NA; |
87 | |
88 | |
89 | // this is the external name of the target server. |
90 | // it is set by the parseExcsatrd method but not really used for much at this |
91 | // time. one possible use is for logging purposes and in the future it |
92 | // may be placed in the trace. |
93 | String targetExtnam_; |
94 | String extnam_; |
95 | |
96 | // Server Class Name of the target server returned in excsatrd. |
97 | // Again this is something which the driver is not currently using |
98 | // to make any decions. Right now it is just stored for future logging. |
99 | // It does contain some useful information however and possibly |
100 | // the database meta data object will make use of this |
101 | // for example, the product id (prdid) would give this driver an idea of |
102 | // what type of sevrer it is connected to. |
103 | public String targetSrvclsnm_; |
104 | |
105 | // Server Name of the target server returned in excsatrd. |
106 | // Again this is something which we don't currently use but |
107 | // keep it in case we want to log it in some problem determination |
108 | // trace/dump later. |
109 | protected String targetSrvnam_; |
110 | |
111 | // Server Product Release Level of the target server returned in excsatrd. |
112 | // specifies the procuct release level of a ddm server. |
113 | // Again this is something which we don't currently use but |
114 | // keep it in case we want to log it in some problem determination |
115 | // trace/dump later. |
116 | public String targetSrvrlslv_; |
117 | |
118 | // Keys used for encryption. |
119 | transient byte[] publicKey_; |
120 | transient byte[] targetPublicKey_; |
121 | |
122 | // Product-Specific Data (prddta) sent to the server in the accrdb command. |
123 | // The prddta has a specified format. It is saved in case it is needed again |
124 | // since it takes a little effort to compute. Saving this information is |
125 | // useful for when the connect flows need to be resent (right now the connect |
126 | // flow is resent when this driver disconnects and reconnects with |
127 | // non unicode ccsids. this is done when the server doesn't recoginze the |
128 | // unicode ccsids). |
129 | // |
130 | |
131 | byte[] prddta_; |
132 | |
133 | // Correlation Token of the source sent to the server in the accrdb. |
134 | // It is saved like the prddta in case it is needed for a connect reflow. |
135 | public byte[] crrtkn_; |
136 | |
137 | // The Secmec used by the target. |
138 | // It contains the negotiated security mechanism for the connection. |
139 | // Initially the value of this is 0. It is set only when the server and |
140 | // the target successfully negotiate a security mechanism. |
141 | int targetSecmec_; |
142 | |
143 | // the security mechanism requested by the application |
144 | protected int securityMechanism_; |
145 | |
146 | // stored the password for deferred reset only. |
147 | private transient char[] deferredResetPassword_ = null; |
148 | |
149 | //If Network Server gets null connection from the embedded driver, |
150 | //it sends RDBAFLRM followed by SQLCARD with null SQLException. |
151 | //Client will parse the SQLCARD and set connectionNull to true if the |
152 | //SQLCARD is empty. If connectionNull=true, connect method in |
153 | //ClientDriver will in turn return null connection. |
154 | private boolean connectionNull = false; |
155 | |
156 | private void setDeferredResetPassword(String password) { |
157 | deferredResetPassword_ = (password == null) ? null : flipBits(password.toCharArray()); |
158 | } |
159 | |
160 | private String getDeferredResetPassword() { |
161 | if (deferredResetPassword_ == null) { |
162 | return null; |
163 | } |
164 | String password = new String(flipBits(deferredResetPassword_)); |
165 | flipBits(deferredResetPassword_); // re-encrypt password |
166 | return password; |
167 | } |
168 | |
169 | protected byte[] cnntkn_ = null; |
170 | |
171 | // resource manager Id for XA Connections. |
172 | private int rmId_ = 0; |
173 | protected NetXAResource xares_ = null; |
174 | protected java.util.Hashtable indoubtTransactions_ = null; |
175 | protected int currXACallInfoOffset_ = 0; |
176 | private short seqNo_ = 1; |
177 | |
178 | // Flag to indicate a read only transaction |
179 | protected boolean readOnlyTransaction_ = true; |
180 | |
181 | //---------------------constructors/finalizer--------------------------------- |
182 | |
183 | public NetConnection(NetLogWriter netLogWriter, |
184 | String databaseName, |
185 | java.util.Properties properties) throws SqlException { |
186 | super(netLogWriter, 0, "", -1, databaseName, properties); |
187 | } |
188 | |
189 | public NetConnection(NetLogWriter netLogWriter, |
190 | org.apache.derby.jdbc.ClientBaseDataSource dataSource, |
191 | String user, |
192 | String password) throws SqlException { |
193 | super(netLogWriter, user, password, dataSource); |
194 | setDeferredResetPassword(password); |
195 | } |
196 | |
197 | // For jdbc 1 connections |
198 | public NetConnection(NetLogWriter netLogWriter, |
199 | int driverManagerLoginTimeout, |
200 | String serverName, |
201 | int portNumber, |
202 | String databaseName, |
203 | java.util.Properties properties) throws SqlException { |
204 | super(netLogWriter, driverManagerLoginTimeout, serverName, portNumber, databaseName, properties); |
205 | netAgent_ = (NetAgent) super.agent_; |
206 | if (netAgent_.exceptionOpeningSocket_ != null) { |
207 | throw netAgent_.exceptionOpeningSocket_; |
208 | } |
209 | checkDatabaseName(); |
210 | String password = ClientBaseDataSource.getPassword(properties); |
211 | securityMechanism_ = ClientBaseDataSource.getSecurityMechanism(properties); |
212 | flowConnect(password, securityMechanism_); |
213 | if(!isConnectionNull()) |
214 | completeConnect(); |
215 | } |
216 | |
217 | // For JDBC 2 Connections |
218 | public NetConnection(NetLogWriter netLogWriter, |
219 | String user, |
220 | String password, |
221 | org.apache.derby.jdbc.ClientBaseDataSource dataSource, |
222 | int rmId, |
223 | boolean isXAConn) throws SqlException { |
224 | super(netLogWriter, user, password, isXAConn, dataSource); |
225 | netAgent_ = (NetAgent) super.agent_; |
226 | initialize(user, password, dataSource, rmId, isXAConn); |
227 | } |
228 | |
229 | public NetConnection(NetLogWriter netLogWriter, |
230 | String ipaddr, |
231 | int portNumber, |
232 | org.apache.derby.jdbc.ClientBaseDataSource dataSource, |
233 | boolean isXAConn) throws SqlException { |
234 | super(netLogWriter, isXAConn, dataSource); |
235 | netAgent_ = (NetAgent) super.agent_; |
236 | if (netAgent_.exceptionOpeningSocket_ != null) { |
237 | throw netAgent_.exceptionOpeningSocket_; |
238 | } |
239 | checkDatabaseName(); |
240 | this.isXAConnection_ = isXAConn; |
241 | flowSimpleConnect(); |
242 | productID_ = targetSrvrlslv_; |
243 | super.completeConnect(); |
244 | } |
245 | |
246 | // For JDBC 2 Connections |
247 | /** |
248 | * This constructor is called from the ClientPooledConnection object |
249 | * to enable the NetConnection to pass <code>this</code> on to the associated |
250 | * prepared statement object thus enabling the prepared statement object |
251 | * to inturn raise the statement events to the ClientPooledConnection object |
252 | * @param netLogWriter NetLogWriter object associated with this connection |
253 | * @param user user id for this connection |
254 | * @param password password for this connection |
255 | * @param dataSource The DataSource object passed from the PooledConnection |
256 | * object from which this constructor was called |
257 | * @param rmId The Resource manager ID for XA Connections |
258 | * @param isXAConn true if this is a XA connection |
259 | * @param cpc The ClientPooledConnection object from which this |
260 | * NetConnection constructor was called. This is used |
261 | * to pass StatementEvents back to the pooledConnection |
262 | * object |
263 | * @throws SqlException |
264 | */ |
265 | |
266 | public NetConnection(NetLogWriter netLogWriter, |
267 | String user, |
268 | String password, |
269 | org.apache.derby.jdbc.ClientBaseDataSource dataSource, |
270 | int rmId, |
271 | boolean isXAConn, |
272 | ClientPooledConnection cpc) throws SqlException { |
273 | super(netLogWriter, user, password, isXAConn, dataSource); |
274 | netAgent_ = (NetAgent) super.agent_; |
275 | initialize(user, password, dataSource, rmId, isXAConn); |
276 | this.pooledConnection_=cpc; |
277 | } |
278 | |
279 | private void initialize(String user, |
280 | String password, |
281 | org.apache.derby.jdbc.ClientBaseDataSource dataSource, |
282 | int rmId, |
283 | boolean isXAConn) throws SqlException { |
284 | securityMechanism_ = dataSource.getSecurityMechanism(password); |
285 | |
286 | setDeferredResetPassword(password); |
287 | checkDatabaseName(); |
288 | dataSource_ = dataSource; |
289 | this.rmId_ = rmId; |
290 | this.isXAConnection_ = isXAConn; |
291 | flowConnect(password, securityMechanism_); |
292 | completeConnect(); |
293 | |
294 | } |
295 | |
296 | // preferably without password in the method signature. |
297 | // We can probally get rid of flowReconnect method. |
298 | public void resetNetConnection(org.apache.derby.client.am.LogWriter logWriter, |
299 | String user, |
300 | String password, |
301 | org.apache.derby.jdbc.ClientBaseDataSource ds, |
302 | boolean recomputeFromDataSource) throws SqlException { |
303 | super.resetConnection(logWriter, user, ds, recomputeFromDataSource); |
304 | //---------------------------------------------------- |
305 | if (recomputeFromDataSource) { |
306 | // do not reset managers on a connection reset. this information shouldn't |
307 | // change and can be used to check secmec support. |
308 | |
309 | targetExtnam_ = null; |
310 | targetSrvclsnm_ = null; |
311 | targetSrvnam_ = null; |
312 | targetSrvrlslv_ = null; |
313 | publicKey_ = null; |
314 | targetPublicKey_ = null; |
315 | targetSecmec_ = 0; |
316 | if (ds != null && securityMechanism_ == 0) { |
317 | securityMechanism_ = ds.getSecurityMechanism(password); |
318 | } |
319 | resetConnectionAtFirstSql_ = false; |
320 | |
321 | } |
322 | if (password != null) { |
323 | deferredResetPassword_ = null; |
324 | } else { |
325 | password = getDeferredResetPassword(); |
326 | } |
327 | // properties prddta_ and crrtkn_ will be initialized by |
328 | // calls to constructPrddta() and constructCrrtkn() |
329 | //---------------------------------------------------------- |
330 | boolean isDeferredReset = flowReconnect(password, securityMechanism_); |
331 | completeReset(isDeferredReset, recomputeFromDataSource); |
332 | } |
333 | |
334 | |
335 | protected void reset_(org.apache.derby.client.am.LogWriter logWriter, |
336 | String user, String password, |
337 | ClientBaseDataSource ds, |
338 | boolean recomputeFromDataSource) throws SqlException { |
339 | checkResetPreconditions(logWriter, user, password, ds); |
340 | resetNetConnection(logWriter, user, password, ds, recomputeFromDataSource); |
341 | } |
342 | |
343 | protected void reset_(org.apache.derby.client.am.LogWriter logWriter, |
344 | ClientBaseDataSource ds, |
345 | boolean recomputeFromDataSource) throws SqlException { |
346 | checkResetPreconditions(logWriter, null, null, ds); |
347 | resetNetConnection(logWriter, ds, recomputeFromDataSource); |
348 | } |
349 | |
350 | private void resetNetConnection(org.apache.derby.client.am.LogWriter logWriter, |
351 | org.apache.derby.jdbc.ClientBaseDataSource ds, |
352 | boolean recomputeFromDataSource) throws SqlException { |
353 | super.resetConnection(logWriter, null, ds, recomputeFromDataSource); |
354 | //---------------------------------------------------- |
355 | if (recomputeFromDataSource) { |
356 | // do not reset managers on a connection reset. this information shouldn't |
357 | // change and can be used to check secmec support. |
358 | |
359 | targetExtnam_ = null; |
360 | targetSrvclsnm_ = null; |
361 | targetSrvnam_ = null; |
362 | targetSrvrlslv_ = null; |
363 | publicKey_ = null; |
364 | targetPublicKey_ = null; |
365 | targetSecmec_ = 0; |
366 | if (ds != null && securityMechanism_ == 0) { |
367 | securityMechanism_ = ds.getSecurityMechanism(); |
368 | } |
369 | resetConnectionAtFirstSql_ = false; |
370 | } |
371 | // properties prddta_ and crrtkn_ will be initialized by |
372 | // calls to constructPrddta() and constructCrrtkn() |
373 | //---------------------------------------------------------- |
374 | boolean isDeferredReset = flowReconnect(null, securityMechanism_); |
375 | completeReset(isDeferredReset, recomputeFromDataSource); |
376 | } |
377 | |
378 | protected void checkResetPreconditions(org.apache.derby.client.am.LogWriter logWriter, |
379 | String user, |
380 | String password, |
381 | ClientBaseDataSource ds) throws SqlException { |
382 | if (inUnitOfWork_) { |
383 | throw new SqlException(logWriter, |
384 | new ClientMessageId(SQLState.NET_CONNECTION_RESET_NOT_ALLOWED_IN_UNIT_OF_WORK)); |
385 | } |
386 | } |
387 | |
388 | java.util.List getSpecialRegisters() { |
389 | if (xares_ != null) { |
390 | return xares_.getSpecialRegisters(); |
391 | } else { |
392 | return null; |
393 | } |
394 | } |
395 | |
396 | public void addSpecialRegisters(String s) { |
397 | if (xares_ != null) { |
398 | xares_.addSpecialRegisters(s); |
399 | } |
400 | } |
401 | |
402 | public void completeConnect() throws SqlException { |
403 | super.completeConnect(); |
404 | } |
405 | |
406 | protected void completeReset(boolean isDeferredReset, boolean recomputeFromDataSource) throws SqlException { |
407 | super.completeReset(isDeferredReset, recomputeFromDataSource); |
408 | } |
409 | |
410 | public void flowConnect(String password, |
411 | int securityMechanism) throws SqlException { |
412 | netAgent_ = (NetAgent) super.agent_; |
413 | constructExtnam(); |
414 | // these calls need to be after newing up the agent |
415 | // because they require the ccsid manager |
416 | constructPrddta(); // construct product data |
417 | |
418 | netAgent_.typdef_ = new Typdef(netAgent_, 1208, NetConfiguration.SYSTEM_ASC, 1200, 1208); |
419 | netAgent_.targetTypdef_ = new Typdef(netAgent_); |
420 | netAgent_.originalTargetTypdef_ = netAgent_.targetTypdef_; |
421 | setDeferredResetPassword(password); |
422 | try { |
423 | switch (securityMechanism) { |
424 | case NetConfiguration.SECMEC_USRIDPWD: // Clear text user id and password |
425 | checkUserPassword(user_, password); |
426 | flowUSRIDPWDconnect(password); |
427 | break; |
428 | case NetConfiguration.SECMEC_USRIDONL: // Clear text user, no password sent to server |
429 | checkUser(user_); |
430 | flowUSRIDONLconnect(); |
431 | break; |
432 | case NetConfiguration.SECMEC_USRENCPWD: // Clear text user, encrypted password |
433 | checkUserPassword(user_, password); |
434 | flowUSRENCPWDconnect(password); |
435 | break; |
436 | case NetConfiguration.SECMEC_EUSRIDPWD: // Encrypted user, encrypted password |
437 | checkUserPassword(user_, password); |
438 | flowEUSRIDPWDconnect(password); |
439 | break; |
440 | case NetConfiguration.SECMEC_EUSRIDDTA: |
441 | checkUserPassword(user_, password); |
442 | flowEUSRIDDTAconnect(); |
443 | break; |
444 | case NetConfiguration.SECMEC_EUSRPWDDTA: |
445 | checkUserPassword(user_, password); |
446 | flowEUSRPWDDTAconnect(password); |
447 | break; |
448 | |
449 | default: |
450 | throw new SqlException(agent_.logWriter_, |
451 | new ClientMessageId(SQLState.SECMECH_NOT_SUPPORTED), |
452 | new Integer(securityMechanism)); |
453 | } |
454 | } catch (java.lang.Throwable e) { // if *anything* goes wrong, make sure the connection is destroyed |
455 | // always mark the connection closed in case of an error. |
456 | // This prevents attempts to use this closed connection |
457 | // to retrieve error message text if an error SQLCA |
458 | // is returned in one of the connect flows. |
459 | open_ = false; |
460 | // logWriter may be closed in agent_.close(), |
461 | // so SqlException needs to be created before that |
462 | // but to be thrown after. |
463 | SqlException exceptionToBeThrown; |
464 | if (e instanceof SqlException) // rethrow original exception if it's an SqlException |
465 | { |
466 | exceptionToBeThrown = (SqlException) e; |
467 | } else // any other exceptions will be wrapped by an SqlException first |
468 | { |
469 | exceptionToBeThrown = new SqlException(agent_.logWriter_, |
470 | new ClientMessageId(SQLState.JAVA_EXCEPTION), |
471 | e.getClass().getName(), e.getMessage(), e); |
472 | } |
473 | |
474 | try { |
475 | if (agent_ != null) { |
476 | agent_.close(); |
477 | } |
478 | } catch (SqlException ignoreMe) { |
479 | } |
480 | |
481 | throw exceptionToBeThrown; |
482 | } |
483 | } |
484 | |
485 | protected void flowSimpleConnect() throws SqlException { |
486 | netAgent_ = (NetAgent) super.agent_; |
487 | constructExtnam(); |
488 | // these calls need to be after newing up the agent |
489 | // because they require the ccsid manager |
490 | constructPrddta(); // construct product data |
491 | |
492 | netAgent_.typdef_ = new Typdef(netAgent_, 1208, NetConfiguration.SYSTEM_ASC, 1200, 1208); |
493 | netAgent_.targetTypdef_ = new Typdef(netAgent_); |
494 | netAgent_.originalTargetTypdef_ = netAgent_.targetTypdef_; |
495 | |
496 | try { |
497 | flowServerAttributes(); |
498 | } catch (java.lang.Throwable e) { // if *anything* goes wrong, make sure the connection is destroyed |
499 | // always mark the connection closed in case of an error. |
500 | // This prevents attempts to use this closed connection |
501 | // to retrieve error message text if an error SQLCA |
502 | // is returned in one of the connect flows. |
503 | open_ = false; |
504 | // logWriter may be closed in agent_.close(), |
505 | // so SqlException needs to be created before that |
506 | // but to be thrown after. |
507 | SqlException exceptionToBeThrown; |
508 | if (e instanceof SqlException) // rethrow original exception if it's an SqlException |
509 | { |
510 | exceptionToBeThrown = (SqlException) e; |
511 | } else // any other exceptions will be wrapped by an SqlException first |
512 | { |
513 | exceptionToBeThrown = new SqlException(agent_.logWriter_, |
514 | new ClientMessageId(SQLState.JAVA_EXCEPTION), |
515 | e.getClass().getName(), e.getMessage(), e); |
516 | } |
517 | |
518 | try { |
519 | if (agent_ != null) { |
520 | agent_.close(); |
521 | } |
522 | } catch (SqlException ignoreMe) { |
523 | } |
524 | |
525 | throw exceptionToBeThrown; |
526 | } |
527 | } |
528 | |
529 | protected boolean flowReconnect(String password, int securityMechanism) throws SqlException { |
530 | constructExtnam(); |
531 | // these calls need to be after newing up the agent |
532 | // because they require the ccsid manager |
533 | constructPrddta(); //modify this to not new up an array |
534 | |
535 | checkSecmgrForSecmecSupport(securityMechanism); |
536 | try { |
537 | switch (securityMechanism) { |
538 | case NetConfiguration.SECMEC_USRIDPWD: // Clear text user id and password |
539 | checkUserPassword(user_, password); |
540 | resetConnectionAtFirstSql_ = true; |
541 | setDeferredResetPassword(password); |
542 | return true; |
543 | case NetConfiguration.SECMEC_USRIDONL: // Clear text user, no password sent to server |
544 | checkUser(user_); |
545 | resetConnectionAtFirstSql_ = true; |
546 | return true; |
547 | case NetConfiguration.SECMEC_USRENCPWD: // Clear text user, encrypted password |
548 | checkUserPassword(user_, password); |
549 | resetConnectionAtFirstSql_ = true; |
550 | setDeferredResetPassword(password); |
551 | return true; |
552 | case NetConfiguration.SECMEC_EUSRIDPWD: // Encrypted user, encrypted password |
553 | checkUserPassword(user_, password); |
554 | resetConnectionAtFirstSql_ = true; |
555 | setDeferredResetPassword(password); |
556 | return true; |
557 | case NetConfiguration.SECMEC_EUSRIDDTA: |
558 | checkUserPassword(user_, password); |
559 | resetConnectionAtFirstSql_ = true; |
560 | setDeferredResetPassword(password); |
561 | return true; |
562 | case NetConfiguration.SECMEC_EUSRPWDDTA: |
563 | checkUserPassword(user_, password); |
564 | resetConnectionAtFirstSql_ = true; |
565 | setDeferredResetPassword(password); |
566 | return true; |
567 | default: |
568 | throw new SqlException(agent_.logWriter_, |
569 | new ClientMessageId(SQLState.SECMECH_NOT_SUPPORTED), |
570 | new Integer(securityMechanism)); |
571 | } |
572 | } catch (SqlException sqle) { // this may not be needed because on method up the stack |
573 | open_ = false; // all reset exceptions are caught and wrapped in disconnect exceptions |
574 | try { |
575 | if (agent_ != null) { |
576 | agent_.close(); |
577 | } |
578 | } catch (SqlException ignoreMe) { |
579 | } |
580 | throw sqle; |
581 | } |
582 | } |
583 | |
584 | protected void finalize() throws java.lang.Throwable { |
585 | super.finalize(); |
586 | } |
587 | |
588 | protected byte[] getCnnToken() { |
589 | return cnntkn_; |
590 | } |
591 | |
592 | protected short getSequenceNumber() { |
593 | return ++seqNo_; |
594 | } |
595 | |
596 | //--------------------------------flow methods-------------------------------- |
597 | |
598 | private void flowUSRIDPWDconnect(String password) throws SqlException { |
599 | flowServerAttributesAndKeyExchange(NetConfiguration.SECMEC_USRIDPWD, |
600 | null); // publicKey |
601 | |
602 | flowSecurityCheckAndAccessRdb(targetSecmec_, //securityMechanism |
603 | user_, |
604 | password, |
605 | null, //encryptedUserid |
606 | null); //encryptedPassword |
607 | } |
608 | |
609 | |
610 | private void flowUSRIDONLconnect() throws SqlException { |
611 | flowServerAttributesAndKeyExchange(NetConfiguration.SECMEC_USRIDONL, |
612 | null); //publicKey |
613 | |
614 | flowSecurityCheckAndAccessRdb(targetSecmec_, //securityMechanism |
615 | user_, |
616 | null, //password |
617 | null, //encryptedUserid |
618 | null); //encryptedPassword |
619 | } |
620 | |
621 | |
622 | private void flowUSRENCPWDconnect(String password) throws SqlException { |
623 | flowServerAttributes(); |
624 | |
625 | checkSecmgrForSecmecSupport(NetConfiguration.SECMEC_USRENCPWD); |
626 | initializePublicKeyForEncryption(); |
627 | flowKeyExchange(NetConfiguration.SECMEC_USRENCPWD, publicKey_); |
628 | |
629 | flowSecurityCheckAndAccessRdb(targetSecmec_, //securityMechanism |
630 | user_, |
631 | null, //password |
632 | null, //encryptedUserid |
633 | encryptedPasswordForUSRENCPWD(password)); |
634 | } |
635 | |
636 | |
637 | private void flowEUSRIDPWDconnect(String password) throws SqlException { |
638 | flowServerAttributes(); |
639 | |
640 | checkSecmgrForSecmecSupport(NetConfiguration.SECMEC_EUSRIDPWD); |
641 | initializePublicKeyForEncryption(); |
642 | flowKeyExchange(NetConfiguration.SECMEC_EUSRIDPWD, publicKey_); |
643 | |
644 | flowSecurityCheckAndAccessRdb(targetSecmec_, //securityMechanism |
645 | null, //user |
646 | null, //password |
647 | encryptedUseridForEUSRIDPWD(), |
648 | encryptedPasswordForEUSRIDPWD(password)); |
649 | } |
650 | |
651 | private void flowEUSRIDDTAconnect() throws SqlException { |
652 | flowServerAttributes(); |
653 | |
654 | checkSecmgrForSecmecSupport(NetConfiguration.SECMEC_EUSRIDPWD); |
655 | initializePublicKeyForEncryption(); |
656 | flowKeyExchange(NetConfiguration.SECMEC_EUSRIDDTA, publicKey_); |
657 | |
658 | |
659 | flowSecurityCheckAndAccessRdb(targetSecmec_, //securityMechanism |
660 | null, //user |
661 | null, //password |
662 | encryptedUseridForEUSRIDPWD(), |
663 | null);//encryptedPasswordForEUSRIDPWD (password), |
664 | } |
665 | |
666 | private void flowEUSRPWDDTAconnect(String password) throws SqlException { |
667 | flowServerAttributes(); |
668 | |
669 | checkSecmgrForSecmecSupport(NetConfiguration.SECMEC_EUSRPWDDTA); |
670 | initializePublicKeyForEncryption(); |
671 | flowKeyExchange(NetConfiguration.SECMEC_EUSRPWDDTA, publicKey_); |
672 | |
673 | |
674 | flowSecurityCheckAndAccessRdb(targetSecmec_, //securityMechanism |
675 | null, //user |
676 | null, //password |
677 | encryptedUseridForEUSRIDPWD(), |
678 | encryptedPasswordForEUSRIDPWD(password)); |
679 | } |
680 | |
681 | private void flowServerAttributes() throws SqlException { |
682 | agent_.beginWriteChainOutsideUOW(); |
683 | netAgent_.netConnectionRequest_.writeExchangeServerAttributes(extnam_, //externalName |
684 | targetAgent_, |
685 | netAgent_.targetSqlam_, |
686 | targetRdb_, |
687 | targetSecmgr_, |
688 | targetCmntcpip_, |
689 | targetCmnappc_, |
690 | targetXamgr_, |
691 | targetSyncptmgr_, |
692 | targetRsyncmgr_); |
693 | agent_.flowOutsideUOW(); |
694 | netAgent_.netConnectionReply_.readExchangeServerAttributes(this); |
695 | agent_.endReadChain(); |
696 | } |
697 | |
698 | private void flowKeyExchange(int securityMechanism, byte[] publicKey) throws SqlException { |
699 | agent_.beginWriteChainOutsideUOW(); |
700 | netAgent_.netConnectionRequest_.writeAccessSecurity(securityMechanism, |
701 | databaseName_, |
702 | publicKey); |
703 | agent_.flowOutsideUOW(); |
704 | netAgent_.netConnectionReply_.readAccessSecurity(this, securityMechanism); |
705 | agent_.endReadChain(); |
706 | } |
707 | |
708 | private void flowServerAttributesAndKeyExchange(int securityMechanism, |
709 | byte[] publicKey) throws SqlException { |
710 | agent_.beginWriteChainOutsideUOW(); |
711 | writeServerAttributesAndKeyExchange(securityMechanism, publicKey); |
712 | agent_.flowOutsideUOW(); |
713 | readServerAttributesAndKeyExchange(securityMechanism); |
714 | agent_.endReadChain(); |
715 | } |
716 | |
717 | private void flowSecurityCheckAndAccessRdb(int securityMechanism, |
718 | String user, |
719 | String password, |
720 | byte[] encryptedUserid, |
721 | byte[] encryptedPassword) throws SqlException { |
722 | agent_.beginWriteChainOutsideUOW(); |
723 | writeSecurityCheckAndAccessRdb(securityMechanism, |
724 | user, |
725 | password, |
726 | encryptedUserid, |
727 | encryptedPassword); |
728 | agent_.flowOutsideUOW(); |
729 | readSecurityCheckAndAccessRdb(); |
730 | agent_.endReadChain(); |
731 | } |
732 | |
733 | private void writeAllConnectCommandsChained(int securityMechanism, |
734 | String user, |
735 | String password) throws SqlException { |
736 | writeServerAttributesAndKeyExchange(securityMechanism, |
737 | null); // publicKey |
738 | writeSecurityCheckAndAccessRdb(securityMechanism, |
739 | user, |
740 | password, |
741 | null, //encryptedUserid |
742 | null); //encryptedPassword, |
743 | } |
744 | |
745 | private void readAllConnectCommandsChained(int securityMechanism) throws SqlException { |
746 | readServerAttributesAndKeyExchange(securityMechanism); |
747 | readSecurityCheckAndAccessRdb(); |
748 | } |
749 | |
750 | private void writeServerAttributesAndKeyExchange(int securityMechanism, |
751 | byte[] publicKey) throws SqlException { |
752 | netAgent_.netConnectionRequest_.writeExchangeServerAttributes(extnam_, //externalName |
753 | targetAgent_, |
754 | netAgent_.targetSqlam_, |
755 | targetRdb_, |
756 | targetSecmgr_, |
757 | targetCmntcpip_, |
758 | targetCmnappc_, |
759 | targetXamgr_, |
760 | targetSyncptmgr_, |
761 | targetRsyncmgr_); |
762 | netAgent_.netConnectionRequest_.writeAccessSecurity(securityMechanism, |
763 | databaseName_, |
764 | publicKey); |
765 | } |
766 | |
767 | private void readServerAttributesAndKeyExchange(int securityMechanism) throws SqlException { |
768 | netAgent_.netConnectionReply_.readExchangeServerAttributes(this); |
769 | netAgent_.netConnectionReply_.readAccessSecurity(this, securityMechanism); |
770 | } |
771 | |
772 | private void writeSecurityCheckAndAccessRdb(int securityMechanism, |
773 | String user, |
774 | String password, |
775 | byte[] encryptedUserid, |
776 | byte[] encryptedPassword) throws SqlException { |
777 | netAgent_.netConnectionRequest_.writeSecurityCheck(securityMechanism, |
778 | databaseName_, |
779 | user, |
780 | password, |
781 | encryptedUserid, |
782 | encryptedPassword); |
783 | netAgent_.netConnectionRequest_.writeAccessDatabase(databaseName_, |
784 | false, |
785 | crrtkn_, |
786 | prddta_, |
787 | netAgent_.typdef_); |
788 | } |
789 | |
790 | private void cacheConnectBytes(int beginOffset, int endOffset) { |
791 | int length = endOffset - beginOffset; |
792 | cachedConnectBytes_ = new byte[length]; |
793 | netAgent_.netConnectionRequest_.finalizePreviousChainedDss(false); |
794 | System.arraycopy(netAgent_.netConnectionRequest_.bytes_, |
795 | beginOffset, |
796 | cachedConnectBytes_, |
797 | 0, |
798 | length); |
799 | netAgent_.netConnectionRequest_.setDssLengthLocation(netAgent_.netConnectionRequest_.offset_); |
800 | } |
801 | |
802 | private void readSecurityCheckAndAccessRdb() throws SqlException { |
803 | netAgent_.netConnectionReply_.readSecurityCheck(this); |
804 | netAgent_.netConnectionReply_.readAccessDatabase(this); |
805 | } |
806 | |
807 | void writeDeferredReset() throws SqlException { |
808 | if (canUseCachedConnectBytes_ && cachedConnectBytes_ != null && |
809 | (securityMechanism_ == NetConfiguration.SECMEC_USRIDPWD || |
810 | securityMechanism_ == NetConfiguration.SECMEC_USRIDONL)) { |
811 | writeDeferredResetFromCache(); |
812 | wroteConnectFromCache_ = true; |
813 | } else { |
814 | int beginOffset = netAgent_.netConnectionRequest_.offset_; |
815 | int endOffset = 0; |
816 | // NetConfiguration.SECMEC_USRIDPWD |
817 | if (securityMechanism_ == NetConfiguration.SECMEC_USRIDPWD) { |
818 | writeAllConnectCommandsChained(NetConfiguration.SECMEC_USRIDPWD, |
819 | user_, |
820 | getDeferredResetPassword()); |
821 | endOffset = netAgent_.netConnectionRequest_.offset_; |
822 | cacheConnectBytes(beginOffset, endOffset); |
823 | } |
824 | // NetConfiguration.SECMEC_USRIDONL |
825 | else if (securityMechanism_ == NetConfiguration.SECMEC_USRIDONL) { |
826 | writeAllConnectCommandsChained(NetConfiguration.SECMEC_USRIDONL, |
827 | user_, |
828 | null); //password |
829 | endOffset = netAgent_.netConnectionRequest_.offset_; |
830 | cacheConnectBytes(beginOffset, endOffset); |
831 | } |
832 | // either NetConfiguration.SECMEC_USRENCPWD or NetConfiguration.SECMEC_EUSRIDPWD |
833 | else { |
834 | initializePublicKeyForEncryption(); |
835 | // Set the resetConnectionAtFirstSql_ to false to avoid going in an |
836 | // infinite loop, since all the flow methods call beginWriteChain which then |
837 | // calls writeDeferredResetConnection where the check for resetConnectionAtFirstSql_ |
838 | // is done. By setting the resetConnectionAtFirstSql_ to false will avoid calling the |
839 | // writeDeferredReset method again. |
840 | resetConnectionAtFirstSql_ = false; |
841 | flowServerAttributesAndKeyExchange(securityMechanism_, publicKey_); |
842 | agent_.beginWriteChainOutsideUOW(); |
843 | |
844 | // Reset the resetConnectionAtFirstSql_ to true since we are done |
845 | // with the flow method. |
846 | resetConnectionAtFirstSql_ = true; |
847 | // NetConfiguration.SECMEC_USRENCPWD |
848 | if (securityMechanism_ == NetConfiguration.SECMEC_USRENCPWD) { |
849 | writeSecurityCheckAndAccessRdb(NetConfiguration.SECMEC_USRENCPWD, |
850 | user_, |
851 | null, //password |
852 | null, //encryptedUserid |
853 | encryptedPasswordForUSRENCPWD(getDeferredResetPassword())); |
854 | } |
855 | // NetConfiguration.SECMEC_EUSRIDPWD |
856 | else { |
857 | writeSecurityCheckAndAccessRdb(NetConfiguration.SECMEC_EUSRIDPWD, |
858 | null, //user |
859 | null, //password |
860 | encryptedUseridForEUSRIDPWD(), |
861 | encryptedPasswordForEUSRIDPWD(getDeferredResetPassword())); |
862 | } |
863 | } |
864 | } |
865 | } |
866 | |
867 | void readDeferredReset() throws SqlException { |
868 | resetConnectionAtFirstSql_ = false; |
869 | if (wroteConnectFromCache_) { |
870 | netAgent_.netConnectionReply_.verifyDeferredReset(); |
871 | return; |
872 | } |
873 | // either NetConfiguration.SECMEC_USRIDPWD or NetConfiguration.SECMEC_USRIDONL |
874 | if (securityMechanism_ == NetConfiguration.SECMEC_USRIDPWD || |
875 | securityMechanism_ == NetConfiguration.SECMEC_USRIDONL) { |
876 | readAllConnectCommandsChained(securityMechanism_); |
877 | } |
878 | // either NetConfiguration.SECMEC_USRENCPWD or NetConfiguration.SECMEC_EUSRIDPWD |
879 | else { |
880 | // either NetConfiguration.SECMEC_USRENCPWD or NetConfiguration.SECMEC_EUSRIDPWD |
881 | readSecurityCheckAndAccessRdb(); |
882 | } |
883 | if (agent_.loggingEnabled()) { |
884 | agent_.logWriter_.traceConnectResetExit(this); |
885 | } |
886 | } |
887 | |
888 | //-------------------parse callback methods-------------------------------- |
889 | |
890 | void setServerAttributeData(String extnam, |
891 | String srvclsnm, |
892 | String srvnam, |
893 | String srvrlslv) { |
894 | targetExtnam_ = extnam; // any of these could be null |
895 | targetSrvclsnm_ = srvclsnm; // since then can be optionally returned from the |
896 | targetSrvnam_ = srvnam; // server |
897 | targetSrvrlslv_ = srvrlslv; |
898 | } |
899 | |
900 | // secmecList is always required and will not be null. |
901 | // secchkcd has an implied severity of error. |
902 | // it will be returned if an error is detected. |
903 | // if no errors and security mechanism requires a sectkn, then |
904 | void setAccessSecurityData(int secchkcd, |
905 | int desiredSecmec, |
906 | int[] secmecList, |
907 | boolean sectknReceived, |
908 | byte[] sectkn) throws DisconnectException { |
909 | // - if the secchkcd is not 0, then map to an exception. |
910 | if (secchkcd != CodePoint.SECCHKCD_00) { |
911 | // the implied severity code is error |
912 | netAgent_.setSvrcod(CodePoint.SVRCOD_ERROR); |
913 | agent_.accumulateReadException(mapSecchkcd(secchkcd)); |
914 | } else { |
915 | // - verify that the secmec parameter reflects the value sent |
916 | // in the ACCSEC command. |
917 | // should we check for null list |
918 | if ((secmecList.length == 1) && |
919 | (secmecList[0] == desiredSecmec)) { |
920 | // the security mechanism returned from the server matches |
921 | // the mechanism requested by the client. |
922 | targetSecmec_ = secmecList[0]; |
923 | |
924 | if ((targetSecmec_ == NetConfiguration.SECMEC_USRENCPWD) || |
925 | (targetSecmec_ == NetConfiguration.SECMEC_EUSRIDPWD) || |
926 | (targetSecmec_ == NetConfiguration.SECMEC_EUSRIDDTA) || |
927 | (targetSecmec_ == NetConfiguration.SECMEC_EUSRPWDDTA)) { |
928 | |
929 | // a security token is required for USRENCPWD, or EUSRIDPWD. |
930 | if (!sectknReceived) { |
931 | agent_.accumulateChainBreakingReadExceptionAndThrow( |
932 | new DisconnectException(agent_, |
933 | new ClientMessageId(SQLState.NET_SECTKN_NOT_RETURNED))); |
934 | } else { |
935 | targetPublicKey_ = sectkn; |
936 | if (encryptionManager_ != null) { |
937 | encryptionManager_.resetSecurityKeys(); |
938 | } |
939 | } |
940 | } |
941 | } else { |
942 | // accumulate an SqlException and don't disconnect yet |
943 | // if a SECCHK was chained after this it would receive a secchk code |
944 | // indicating the security mechanism wasn't supported and that would be a |
945 | // chain breaking exception. if no SECCHK is chained this exception |
946 | // will be surfaced by endReadChain |
947 | // agent_.accumulateChainBreakingReadExceptionAndThrow ( |
948 | // new DisconnectException (agent_,"secmec not supported ","0000", -999)); |
949 | agent_.accumulateReadException(new SqlException(agent_.logWriter_, |
950 | new ClientMessageId(SQLState.NET_SECKTKN_NOT_RETURNED))); |
951 | } |
952 | } |
953 | } |
954 | |
955 | void securityCheckComplete(int svrcod, int secchkcd) { |
956 | netAgent_.setSvrcod(svrcod); |
957 | if (secchkcd == CodePoint.SECCHKCD_00) { |
958 | return; |
959 | } |
960 | agent_.accumulateReadException(mapSecchkcd(secchkcd)); |
961 | } |
962 | |
963 | void rdbAccessed(int svrcod, |
964 | String prdid, |
965 | boolean crrtknReceived, |
966 | byte[] crrtkn) { |
967 | if (crrtknReceived) { |
968 | crrtkn_ = crrtkn; |
969 | } |
970 | |
971 | netAgent_.setSvrcod(svrcod); |
972 | productID_ = prdid; |
973 | } |
974 | |
975 | |
976 | //-------------------Abstract object factories-------------------------------- |
977 | |
978 | protected org.apache.derby.client.am.Agent newAgent_(org.apache.derby.client.am.LogWriter logWriter, int loginTimeout, String serverName, int portNumber) |
979 | throws SqlException { |
980 | return new NetAgent(this, |
981 | (NetLogWriter) logWriter, |
982 | loginTimeout, |
983 | serverName, |
984 | portNumber); |
985 | } |
986 | |
987 | |
988 | protected Statement newStatement_(int type, int concurrency, int holdability) throws SqlException { |
989 | return new NetStatement(netAgent_, this, type, concurrency, holdability).statement_; |
990 | } |
991 | |
992 | protected void resetStatement_(Statement statement, int type, int concurrency, int holdability) throws SqlException { |
993 | ((NetStatement) statement.materialStatement_).resetNetStatement(netAgent_, this, type, concurrency, holdability); |
994 | } |
995 | |
996 | protected PreparedStatement newPositionedUpdatePreparedStatement_(String sql, |
997 | org.apache.derby.client.am.Section section) throws SqlException { |
998 | //passing the pooledConnection_ object which will be used to raise |
999 | //StatementEvents to the PooledConnection |
1000 | return new NetPreparedStatement(netAgent_, this, sql, section,pooledConnection_).preparedStatement_; |
1001 | } |
1002 | |
1003 | protected PreparedStatement newPreparedStatement_(String sql, int type, int concurrency, int holdability, int autoGeneratedKeys, String[] columnNames) throws SqlException { |
1004 | |
1005 | //passing the pooledConnection_ object which will be used to raise |
1006 | //StatementEvents to the PooledConnection |
1007 | return new NetPreparedStatement(netAgent_, this, sql, type, concurrency, holdability, autoGeneratedKeys, columnNames,pooledConnection_).preparedStatement_; |
1008 | } |
1009 | |
1010 | protected void resetPreparedStatement_(PreparedStatement ps, |
1011 | String sql, |
1012 | int resultSetType, |
1013 | int resultSetConcurrency, |
1014 | int resultSetHoldability, |
1015 | int autoGeneratedKeys, |
1016 | String[] columnNames) throws SqlException { |
1017 | ((NetPreparedStatement) ps.materialPreparedStatement_).resetNetPreparedStatement(netAgent_, this, sql, resultSetType, resultSetConcurrency, resultSetHoldability, autoGeneratedKeys, columnNames); |
1018 | } |
1019 | |
1020 | |
1021 | protected CallableStatement newCallableStatement_(String sql, int type, int concurrency, int holdability) throws SqlException { |
1022 | //passing the pooledConnection_ object which will be used to raise |
1023 | //StatementEvents to the PooledConnection |
1024 | return new NetCallableStatement(netAgent_, this, sql, type, concurrency, holdability,pooledConnection_).callableStatement_; |
1025 | } |
1026 | |
1027 | protected void resetCallableStatement_(CallableStatement cs, |
1028 | String sql, |
1029 | int resultSetType, |
1030 | int resultSetConcurrency, |
1031 | int resultSetHoldability) throws SqlException { |
1032 | ((NetCallableStatement) cs.materialCallableStatement_).resetNetCallableStatement(netAgent_, this, sql, resultSetType, resultSetConcurrency, resultSetHoldability); |
1033 | } |
1034 | |
1035 | |
1036 | protected DatabaseMetaData newDatabaseMetaData_() { |
1037 | return ClientDriver.getFactory().newNetDatabaseMetaData(netAgent_, this); |
1038 | } |
1039 | |
1040 | //-------------------private helper methods-------------------------------- |
1041 | |
1042 | private void checkDatabaseName() throws SqlException { |
1043 | // netAgent_.logWriter may not be initialized yet |
1044 | if (databaseName_ == null) { |
1045 | throw new SqlException(agent_.logWriter_, |
1046 | new ClientMessageId(SQLState.CONNECT_REQUIRED_PROPERTY_NOT_SET), |
1047 | "databaseName"); |
1048 | } |
1049 | } |
1050 | |
1051 | private void checkUserLength(String user) throws SqlException { |
1052 | int usridLength = user.length(); |
1053 | if ((usridLength == 0) || (usridLength > NetConfiguration.USRID_MAXSIZE)) { |
1054 | throw new SqlException(netAgent_.logWriter_, |
1055 | new ClientMessageId(SQLState.CONNECT_USERID_LENGTH_OUT_OF_RANGE), |
1056 | new Integer(usridLength), |
1057 | new Integer(NetConfiguration.USRID_MAXSIZE)); |
1058 | } |
1059 | } |
1060 | |
1061 | private void checkPasswordLength(String password) throws SqlException { |
1062 | int passwordLength = password.length(); |
1063 | if ((passwordLength == 0) || (passwordLength > NetConfiguration.PASSWORD_MAXSIZE)) { |
1064 | throw new SqlException(netAgent_.logWriter_, |
1065 | new ClientMessageId(SQLState.CONNECT_PASSWORD_LENGTH_OUT_OF_RANGE), |
1066 | new Integer(passwordLength), |
1067 | new Integer(NetConfiguration.PASSWORD_MAXSIZE)); |
1068 | } |
1069 | } |
1070 | |
1071 | private void checkUser(String user) throws SqlException { |
1072 | if (user == null) { |
1073 | throw new SqlException(netAgent_.logWriter_, |
1074 | new ClientMessageId(SQLState.CONNECT_USERID_ISNULL)); |
1075 | } |
1076 | checkUserLength(user); |
1077 | } |
1078 | |
1079 | private void checkUserPassword(String user, String password) throws SqlException { |
1080 | checkUser(user); |
1081 | if (password == null) { |
1082 | throw new SqlException(netAgent_.logWriter_, |
1083 | new ClientMessageId(SQLState.CONNECT_PASSWORD_ISNULL)); |
1084 | } |
1085 | checkPasswordLength(password); |
1086 | } |
1087 | |
1088 | |
1089 | // Determine if a security mechanism is supported by |
1090 | // the security manager used for the connection. |
1091 | // An exception is thrown if the security mechanism is not supported |
1092 | // by the secmgr. |
1093 | private void checkSecmgrForSecmecSupport(int securityMechanism) throws SqlException { |
1094 | boolean secmecSupported = false; |
1095 | int[] supportedSecmecs = null; |
1096 | |
1097 | // Point to a list (array) of supported security mechanisms. |
1098 | supportedSecmecs = NetConfiguration.SECMGR_SECMECS; |
1099 | |
1100 | // check to see if the security mechanism is on the supported list. |
1101 | for (int i = 0; (i < supportedSecmecs.length) && (!secmecSupported); i++) { |
1102 | if (supportedSecmecs[i] == securityMechanism) { |
1103 | secmecSupported = true; |
1104 | } |
1105 | } |
1106 | |
1107 | // throw an exception if not supported (not on list). |
1108 | if (!secmecSupported) { |
1109 | throw new SqlException(agent_.logWriter_, |
1110 | new ClientMessageId(SQLState.SECMECH_NOT_SUPPORTED), |
1111 | new Integer(securityMechanism)); |
1112 | } |
1113 | } |
1114 | |
1115 | // If secchkcd is not 0, map to SqlException |
1116 | // according to the secchkcd received. |
1117 | private SqlException mapSecchkcd(int secchkcd) { |
1118 | if (secchkcd == CodePoint.SECCHKCD_00) { |
1119 | return null; |
1120 | } |
1121 | |
1122 | // the net driver will not support new password at this time. |
1123 | // Here is the message for -30082 (STATE "08001"): |
1124 | // Attempt to establish connection failed with security |
1125 | // reason {0} {1} + reason-code + reason-string. |
1126 | switch (secchkcd) { |
1127 | case CodePoint.SECCHKCD_01: // ERROR SVRCOD |
1128 | return new SqlException(agent_.logWriter_, |
1129 | new ClientMessageId(SQLState.NET_CONNECT_AUTH_FAILED), |
1130 | msgutil.getTextMessage(MessageId.CONN_SECMECH_NOT_SUPPORTED)); |
1131 | case CodePoint.SECCHKCD_10: // ERROR SVRCOD |
1132 | return new SqlException(agent_.logWriter_, |
1133 | new ClientMessageId(SQLState.NET_CONNECT_AUTH_FAILED), |
1134 | msgutil.getTextMessage(MessageId.CONN_PASSWORD_MISSING)); |
1135 | case CodePoint.SECCHKCD_12: // ERROR SVRCOD |
1136 | return new SqlException(agent_.logWriter_, |
1137 | new ClientMessageId(SQLState.NET_CONNECT_AUTH_FAILED), |
1138 | msgutil.getTextMessage(MessageId.CONN_USERID_MISSING)); |
1139 | case CodePoint.SECCHKCD_13: // ERROR SVRCOD |
1140 | return new SqlException(agent_.logWriter_, |
1141 | new ClientMessageId(SQLState.NET_CONNECT_AUTH_FAILED), |
1142 | msgutil.getTextMessage(MessageId.CONN_USERID_OR_PASSWORD_INVALID)); |
1143 | case CodePoint.SECCHKCD_14: // ERROR SVRCOD |
1144 | return new SqlException(agent_.logWriter_, |
1145 | new ClientMessageId(SQLState.NET_CONNECT_AUTH_FAILED), |
1146 | msgutil.getTextMessage(MessageId.CONN_USERID_REVOKED)); |
1147 | case CodePoint.SECCHKCD_15: // ERROR SVRCOD |
1148 | return new SqlException(agent_.logWriter_, |
1149 | new ClientMessageId(SQLState.NET_CONNECT_AUTH_FAILED), |
1150 | msgutil.getTextMessage(MessageId.CONN_NEW_PASSWORD_INVALID)); |
1151 | case CodePoint.SECCHKCD_0A: // ERROR SVRCOD |
1152 | return new SqlException(agent_.logWriter_, |
1153 | new ClientMessageId(SQLState.NET_CONNECT_AUTH_FAILED), |
1154 | msgutil.getTextMessage(MessageId.CONN_SECSVC_NONRETRYABLE_ERR)); |
1155 | case CodePoint.SECCHKCD_0B: // ERROR SVRCOD |
1156 | return new SqlException(agent_.logWriter_, |
1157 | new ClientMessageId(SQLState.NET_CONNECT_AUTH_FAILED), |
1158 | msgutil.getTextMessage(MessageId.CONN_SECTKN_MISSING_OR_INVALID)); |
1159 | case CodePoint.SECCHKCD_0E: // ERROR SVRCOD |
1160 | return new SqlException(agent_.logWriter_, |
1161 | new ClientMessageId(SQLState.NET_CONNECT_AUTH_FAILED), |
1162 | msgutil.getTextMessage(MessageId.CONN_PASSWORD_EXPIRED)); |
1163 | case CodePoint.SECCHKCD_0F: // ERROR SVRCOD |
1164 | return new SqlException(agent_.logWriter_, |
1165 | new ClientMessageId(SQLState.NET_CONNECT_AUTH_FAILED), |
1166 | msgutil.getTextMessage(MessageId.CONN_USERID_OR_PASSWORD_INVALID)); |
1167 | default: // ERROR SVRCOD |
1168 | return new SqlException(agent_.logWriter_, |
1169 | new ClientMessageId(SQLState.NET_CONNECT_AUTH_FAILED), |
1170 | msgutil.getTextMessage(MessageId.CONN_NOT_SPECIFIED)); |
1171 | } |
1172 | } |
1173 | |
1174 | // Construct the correlation token. |
1175 | // The crrtkn has the following format. |
1176 | // |
1177 | // <Almost IP address>.<local port number><current time in millis> |
1178 | // | | | || | |
1179 | // +----+--------------+ +-----+---------++---------+--------+ |
1180 | // | | | |
1181 | // 8 bytes 4 bytes 6 bytes |
1182 | // Total lengtho of 19 bytes. |
1183 | // |
1184 | // 1 char for each 1/2 byte in the IP address. |
1185 | // If the first character of the <IP address> or <port number> |
1186 | // starts with '0' thru '9', it will be mapped to 'G' thru 'P'. |
1187 | // Reason for mapping the IP address is in order to use the crrtkn as the LUWID when using SNA in a hop site. |
1188 | protected void constructCrrtkn() throws SqlException { |
1189 | byte[] localAddressBytes = null; |
1190 | long time = 0; |
1191 | int num = 0; |
1192 | int halfByte = 0; |
1193 | int i = 0; |
1194 | int j = 0; |
1195 | |
1196 | // allocate the crrtkn array. |
1197 | if (crrtkn_ == null) { |
1198 | crrtkn_ = new byte[19]; |
1199 | } else { |
1200 | java.util.Arrays.fill(crrtkn_, (byte) 0); |
1201 | } |
1202 | |
1203 | localAddressBytes = netAgent_.socket_.getLocalAddress().getAddress(); |
1204 | |
1205 | // IP addresses are returned in a 4 byte array. |
1206 | // Obtain the character representation of each half byte. |
1207 | for (i = 0, j = 0; i < 4; i++, j += 2) { |
1208 | |
1209 | // since a byte is signed in java, convert any negative |
1210 | // numbers to positive before shifting. |
1211 | num = localAddressBytes[i] < 0 ? localAddressBytes[i] + 256 : localAddressBytes[i]; |
1212 | halfByte = (num >> 4) & 0x0f; |
1213 | |
1214 | // map 0 to G |
1215 | // The first digit of the IP address is is replaced by |
1216 | // the characters 'G' thro 'P'(in order to use the crrtkn as the LUWID when using |
1217 | // SNA in a hop site). For example, 0 is mapped to G, 1 is mapped H,etc. |
1218 | if (i == 0) { |
1219 | crrtkn_[j] = netAgent_.sourceCcsidManager_.numToSnaRequiredCrrtknChar_[halfByte]; |
1220 | } else { |
1221 | crrtkn_[j] = netAgent_.sourceCcsidManager_.numToCharRepresentation_[halfByte]; |
1222 | } |
1223 | |
1224 | halfByte = (num) & 0x0f; |
1225 | crrtkn_[j + 1] = netAgent_.sourceCcsidManager_.numToCharRepresentation_[halfByte]; |
1226 | } |
1227 | |
1228 | // fill the '.' in between the IP address and the port number |
1229 | crrtkn_[8] = netAgent_.sourceCcsidManager_.dot_; |
1230 | |
1231 | // Port numbers have values which fit in 2 unsigned bytes. |
1232 | // Java returns port numbers in an int so the value is not negative. |
1233 | // Get the character representation by converting the |
1234 | // 4 low order half bytes to the character representation. |
1235 | num = netAgent_.socket_.getLocalPort(); |
1236 | |
1237 | halfByte = (num >> 12) & 0x0f; |
1238 | crrtkn_[9] = netAgent_.sourceCcsidManager_.numToSnaRequiredCrrtknChar_[halfByte]; |
1239 | halfByte = (num >> 8) & 0x0f; |
1240 | crrtkn_[10] = netAgent_.sourceCcsidManager_.numToCharRepresentation_[halfByte]; |
1241 | halfByte = (num >> 4) & 0x0f; |
1242 | crrtkn_[11] = netAgent_.sourceCcsidManager_.numToCharRepresentation_[halfByte]; |
1243 | halfByte = (num) & 0x0f; |
1244 | crrtkn_[12] = netAgent_.sourceCcsidManager_.numToCharRepresentation_[halfByte]; |
1245 | |
1246 | // The final part of CRRTKN is a 6 byte binary number that makes the |
1247 | // crrtkn unique, which is usually the time stamp/process id. |
1248 | // If the new time stamp is the |
1249 | // same as one of the already created ones, then recreate the time stamp. |
1250 | time = System.currentTimeMillis(); |
1251 | |
1252 | for (i = 0; i < 6; i++) { |
1253 | // store 6 bytes of 8 byte time into crrtkn |
1254 | crrtkn_[i + 13] = (byte) (time >>> (40 - (i * 8))); |
1255 | } |
1256 | } |
1257 | |
1258 | |
1259 | private void constructExtnam() throws SqlException { |
1260 | extnam_ = "derbydnc" + java.lang.Thread.currentThread().getName(); |
1261 | } |
1262 | |
1263 | private void constructPrddta() throws SqlException { |
1264 | int prddtaLen = 1; |
1265 | |
1266 | if (prddta_ == null) { |
1267 | prddta_ = new byte[NetConfiguration.PRDDTA_MAXSIZE]; |
1268 | } else { |
1269 | java.util.Arrays.fill(prddta_, (byte) 0); |
1270 | } |
1271 | |
1272 | for (int i = 0; i < NetConfiguration.PRDDTA_ACCT_SUFFIX_LEN_BYTE; i++) { |
1273 | prddta_[i] = netAgent_.sourceCcsidManager_.space_; |
1274 | } |
1275 | |
1276 | prddtaLen = netAgent_.sourceCcsidManager_.convertFromUCS2(NetConfiguration.PRDID, |
1277 | prddta_, |
1278 | prddtaLen, |
1279 | netAgent_); |
1280 | |
1281 | prddtaLen = netAgent_.sourceCcsidManager_.convertFromUCS2(NetConfiguration.PRDDTA_PLATFORM_ID, |
1282 | prddta_, |
1283 | prddtaLen, |
1284 | netAgent_); |
1285 | |
1286 | int extnamTruncateLength = Utils.min(extnam_.length(), NetConfiguration.PRDDTA_APPL_ID_FIXED_LEN); |
1287 | netAgent_.sourceCcsidManager_.convertFromUCS2(extnam_.substring(0, extnamTruncateLength), |
1288 | prddta_, |
1289 | prddtaLen, |
1290 | netAgent_); |
1291 | prddtaLen += NetConfiguration.PRDDTA_APPL_ID_FIXED_LEN; |
1292 | |
1293 | if (user_ != null) { |
1294 | int userTruncateLength = Utils.min(user_.length(), NetConfiguration.PRDDTA_USER_ID_FIXED_LEN); |
1295 | netAgent_.sourceCcsidManager_.convertFromUCS2(user_.substring(0, userTruncateLength), |
1296 | prddta_, |
1297 | prddtaLen, |
1298 | netAgent_); |
1299 | } |
1300 | |
1301 | prddtaLen += NetConfiguration.PRDDTA_USER_ID_FIXED_LEN; |
1302 | |
1303 | prddta_[NetConfiguration.PRDDTA_ACCT_SUFFIX_LEN_BYTE] = 0; |
1304 | prddtaLen++; |
1305 | // the length byte value does not include itself. |
1306 | prddta_[NetConfiguration.PRDDTA_LEN_BYTE] = (byte) (prddtaLen - 1); |
1307 | } |
1308 | |
1309 | private void initializePublicKeyForEncryption() throws SqlException { |
1310 | if (encryptionManager_ == null) { |
1311 | encryptionManager_ = new org.apache.derby.client.am.EncryptionManager(agent_); |
1312 | } |
1313 | publicKey_ = encryptionManager_.obtainPublicKey(); |
1314 | } |
1315 | |
1316 | |
1317 | private byte[] encryptedPasswordForUSRENCPWD(String password) throws SqlException { |
1318 | return encryptionManager_.encryptData(netAgent_.sourceCcsidManager_.convertFromUCS2(password, netAgent_), |
1319 | NetConfiguration.SECMEC_USRENCPWD, |
1320 | netAgent_.sourceCcsidManager_.convertFromUCS2(user_, netAgent_), |
1321 | targetPublicKey_); |
1322 | } |
1323 | |
1324 | private byte[] encryptedUseridForEUSRIDPWD() throws SqlException { |
1325 | return encryptionManager_.encryptData(netAgent_.sourceCcsidManager_.convertFromUCS2(user_, netAgent_), |
1326 | NetConfiguration.SECMEC_EUSRIDPWD, |
1327 | targetPublicKey_, |
1328 | targetPublicKey_); |
1329 | } |
1330 | |
1331 | private byte[] encryptedPasswordForEUSRIDPWD(String password) throws SqlException { |
1332 | return encryptionManager_.encryptData(netAgent_.sourceCcsidManager_.convertFromUCS2(password, netAgent_), |
1333 | NetConfiguration.SECMEC_EUSRIDPWD, |
1334 | targetPublicKey_, |
1335 | targetPublicKey_); |
1336 | } |
1337 | |
1338 | // Methods to get the manager levels for Regression harness only. |
1339 | public int getSQLAM() { |
1340 | return netAgent_.targetSqlam_; |
1341 | } |
1342 | |
1343 | public int getAGENT() { |
1344 | return targetAgent_; |
1345 | } |
1346 | |
1347 | public int getCMNTCPIP() { |
1348 | return targetCmntcpip_; |
1349 | } |
1350 | |
1351 | public int getRDB() { |
1352 | return targetRdb_; |
1353 | } |
1354 | |
1355 | public int getSECMGR() { |
1356 | return targetSecmgr_; |
1357 | } |
1358 | |
1359 | public int getXAMGR() { |
1360 | return targetXamgr_; |
1361 | } |
1362 | |
1363 | public int getSYNCPTMGR() { |
1364 | return targetSyncptmgr_; |
1365 | } |
1366 | |
1367 | public int getRSYNCMGR() { |
1368 | return targetRsyncmgr_; |
1369 | } |
1370 | |
1371 | |
1372 | private char[] flipBits(char[] array) { |
1373 | for (int i = 0; i < array.length; i++) { |
1374 | array[i] ^= 0xff; |
1375 | } |
1376 | return array; |
1377 | } |
1378 | |
1379 | private void writeDeferredResetFromCache() { |
1380 | int length = cachedConnectBytes_.length; |
1381 | System.arraycopy(cachedConnectBytes_, |
1382 | 0, |
1383 | netAgent_.netConnectionRequest_.bytes_, |
1384 | netAgent_.netConnectionRequest_.offset_, |
1385 | length); |
1386 | netAgent_.netConnectionRequest_.offset_ += length; |
1387 | netAgent_.netConnectionRequest_.setDssLengthLocation(netAgent_.netConnectionRequest_.offset_); |
1388 | netAgent_.netConnectionRequest_.setCorrelationID(4); |
1389 | } |
1390 | |
1391 | |
1392 | public void writeCommitSubstitute_() throws SqlException { |
1393 | netAgent_.connectionRequest_.writeCommitSubstitute(this); |
1394 | } |
1395 | |
1396 | public void readCommitSubstitute_() throws SqlException { |
1397 | netAgent_.connectionReply_.readCommitSubstitute(this); |
1398 | } |
1399 | |
1400 | public void writeLocalXAStart_() throws SqlException { |
1401 | netAgent_.connectionRequest_.writeLocalXAStart(this); |
1402 | } |
1403 | |
1404 | public void readLocalXAStart_() throws SqlException { |
1405 | netAgent_.connectionReply_.readLocalXAStart(this); |
1406 | } |
1407 | |
1408 | public void writeLocalXACommit_() throws SqlException { |
1409 | netAgent_.connectionRequest_.writeLocalXACommit(this); |
1410 | } |
1411 | |
1412 | public void readLocalXACommit_() throws SqlException { |
1413 | netAgent_.connectionReply_.readLocalXACommit(this); |
1414 | } |
1415 | |
1416 | public void writeLocalXARollback_() throws SqlException { |
1417 | netAgent_.connectionRequest_.writeLocalXARollback(this); |
1418 | } |
1419 | |
1420 | public void readLocalXARollback_() throws SqlException { |
1421 | netAgent_.connectionReply_.readLocalXARollback(this); |
1422 | } |
1423 | |
1424 | public void writeLocalCommit_() throws SqlException { |
1425 | netAgent_.connectionRequest_.writeLocalCommit(this); |
1426 | } |
1427 | |
1428 | public void readLocalCommit_() throws SqlException { |
1429 | netAgent_.connectionReply_.readLocalCommit(this); |
1430 | } |
1431 | |
1432 | public void writeLocalRollback_() throws SqlException { |
1433 | netAgent_.connectionRequest_.writeLocalRollback(this); |
1434 | } |
1435 | |
1436 | public void readLocalRollback_() throws SqlException { |
1437 | netAgent_.connectionReply_.readLocalRollback(this); |
1438 | } |
1439 | |
1440 | |
1441 | protected void markClosed_() { |
1442 | } |
1443 | |
1444 | protected boolean isGlobalPending_() { |
1445 | return false; |
1446 | } |
1447 | |
1448 | protected boolean doCloseStatementsOnClose_() { |
1449 | return true; |
1450 | } |
1451 | |
1452 | protected boolean allowCloseInUOW_() { |
1453 | return false; |
1454 | } |
1455 | |
1456 | // Driver-specific determination if local COMMIT/ROLLBACK is allowed; |
1457 | // Allow local COMMIT/ROLLBACK only if we are not in an XA transaction |
1458 | protected boolean allowLocalCommitRollback_() throws org.apache.derby.client.am.SqlException { |
1459 | |
1460 | if (getXAState() == XA_T0_NOT_ASSOCIATED) { |
1461 | return true; |
1462 | } |
1463 | return false; |
1464 | } |
1465 | |
1466 | public void setInputStream(java.io.InputStream inputStream) { |
1467 | netAgent_.setInputStream(inputStream); |
1468 | } |
1469 | |
1470 | public void setOutputStream(java.io.OutputStream outputStream) { |
1471 | netAgent_.setOutputStream(outputStream); |
1472 | } |
1473 | |
1474 | public java.io.InputStream getInputStream() { |
1475 | return netAgent_.getInputStream(); |
1476 | } |
1477 | |
1478 | public java.io.OutputStream getOutputStream() { |
1479 | return netAgent_.getOutputStream(); |
1480 | } |
1481 | |
1482 | |
1483 | public void writeTransactionStart(Statement statement) throws SqlException { |
1484 | } |
1485 | |
1486 | public void readTransactionStart() throws SqlException { |
1487 | super.readTransactionStart(); |
1488 | } |
1489 | |
1490 | public void setIndoubtTransactions(java.util.Hashtable indoubtTransactions) { |
1491 | if (isXAConnection_) { |
1492 | if (indoubtTransactions_ != null) { |
1493 | indoubtTransactions_.clear(); |
1494 | } |
1495 | indoubtTransactions_ = indoubtTransactions; |
1496 | } |
1497 | } |
1498 | |
1499 | protected void setReadOnlyTransactionFlag(boolean flag) { |
1500 | readOnlyTransaction_ = flag; |
1501 | } |
1502 | |
1503 | public org.apache.derby.client.am.SectionManager newSectionManager |
1504 | (String collection, |
1505 | org.apache.derby.client.am.Agent agent, |
1506 | String databaseName) { |
1507 | return new org.apache.derby.client.am.SectionManager(collection, agent, databaseName); |
1508 | } |
1509 | |
1510 | protected int getSocketAndInputOutputStreams(String server, int port) { |
1511 | try { |
1512 | netAgent_.socket_ = (java.net.Socket) java.security.AccessController.doPrivileged(new OpenSocketAction(server, port)); |
1513 | } catch (java.security.PrivilegedActionException e) { |
1514 | Exception openSocketException = e.getException(); |
1515 | if (netAgent_.loggingEnabled()) { |
1516 | netAgent_.logWriter_.tracepoint("[net]", 101, "Client Re-route: " + openSocketException.getClass().getName() + " : " + openSocketException.getMessage()); |
1517 | } |
1518 | return -1; |
1519 | } |
1520 | |
1521 | try { |
1522 | netAgent_.rawSocketOutputStream_ = netAgent_.socket_.getOutputStream(); |
1523 | netAgent_.rawSocketInputStream_ = netAgent_.socket_.getInputStream(); |
1524 | } catch (java.io.IOException e) { |
1525 | if (netAgent_.loggingEnabled()) { |
1526 | netAgent_.logWriter_.tracepoint("[net]", 103, "Client Re-route: java.io.IOException " + e.getMessage()); |
1527 | } |
1528 | try { |
1529 | netAgent_.socket_.close(); |
1530 | } catch (java.io.IOException doNothing) { |
1531 | } |
1532 | return -1; |
1533 | } |
1534 | return 0; |
1535 | } |
1536 | |
1537 | protected int checkAlternateServerHasEqualOrHigherProductLevel(ProductLevel orgLvl, int orgServerType) { |
1538 | if (orgLvl == null && orgServerType == 0) { |
1539 | return 0; |
1540 | } |
1541 | ProductLevel alternateServerProductLvl = |
1542 | netAgent_.netConnection_.databaseMetaData_.productLevel_; |
1543 | boolean alternateServerIsEqualOrHigherToOriginalServer = |
1544 | (alternateServerProductLvl.greaterThanOrEqualTo |
1545 | (orgLvl.versionLevel_, |
1546 | orgLvl.releaseLevel_, |
1547 | orgLvl.modificationLevel_)) ? true : false; |
1548 | // write an entry to the trace |
1549 | if (!alternateServerIsEqualOrHigherToOriginalServer && |
1550 | netAgent_.loggingEnabled()) { |
1551 | netAgent_.logWriter_.tracepoint("[net]", |
1552 | 99, |
1553 | "Client Re-route failed because the alternate server is on a lower product level than the origianl server."); |
1554 | } |
1555 | return (alternateServerIsEqualOrHigherToOriginalServer) ? 0 : -1; |
1556 | } |
1557 | |
1558 | public boolean willAutoCommitGenerateFlow() { |
1559 | // this logic must be in sync with writeCommit() logic |
1560 | if (!autoCommit_) { |
1561 | return false; |
1562 | } |
1563 | if (!isXAConnection_) { |
1564 | return true; |
1565 | } |
1566 | boolean doCommit = false; |
1567 | int xaState = getXAState(); |
1568 | |
1569 | |
1570 | if (xaState == XA_T0_NOT_ASSOCIATED) { |
1571 | doCommit = true; |
1572 | } |
1573 | |
1574 | return doCommit; |
1575 | } |
1576 | |
1577 | public int getSecurityMechanism() { |
1578 | return securityMechanism_; |
1579 | } |
1580 | |
1581 | public EncryptionManager getEncryptionManager() { |
1582 | return encryptionManager_; |
1583 | } |
1584 | |
1585 | public byte[] getTargetPublicKey() { |
1586 | return targetPublicKey_; |
1587 | } |
1588 | |
1589 | public String getProductID() { |
1590 | return targetSrvclsnm_; |
1591 | } |
1592 | |
1593 | public void doResetNow() throws SqlException { |
1594 | if (!resetConnectionAtFirstSql_) { |
1595 | return; // reset not needed |
1596 | } |
1597 | agent_.beginWriteChainOutsideUOW(); |
1598 | agent_.flowOutsideUOW(); |
1599 | agent_.endReadChain(); |
1600 | } |
1601 | |
1602 | /** |
1603 | * @return Returns the connectionNull. |
1604 | */ |
1605 | public boolean isConnectionNull() { |
1606 | return connectionNull; |
1607 | } |
1608 | /** |
1609 | * @param connectionNull The connectionNull to set. |
1610 | */ |
1611 | public void setConnectionNull(boolean connectionNull) { |
1612 | this.connectionNull = connectionNull; |
1613 | } |
1614 | |
1615 | /** |
1616 | * Check whether the server has full support for the QRYCLSIMP |
1617 | * parameter in OPNQRY. |
1618 | * |
1619 | * @return true if QRYCLSIMP is fully supported |
1620 | */ |
1621 | public final boolean serverSupportsQryclsimp() { |
1622 | NetDatabaseMetaData metadata = |
1623 | (NetDatabaseMetaData) databaseMetaData_; |
1624 | return metadata.serverSupportsQryclsimp(); |
1625 | } |
1626 | |
1627 | /** |
1628 | * Returns if a transaction is in process |
1629 | * @return open |
1630 | */ |
1631 | public boolean isOpen() { |
1632 | return open_; |
1633 | } |
1634 | |
1635 | /** |
1636 | * closes underlying connection and associated resource. |
1637 | */ |
1638 | synchronized public void close() throws SQLException { |
1639 | // call super.close*() to do the close* |
1640 | super.close(); |
1641 | if (!isXAConnection_) |
1642 | return; |
1643 | if (isOpen()) { |
1644 | return; // still open, return |
1645 | } |
1646 | if (xares_ != null) { |
1647 | xares_.removeXaresFromSameRMchain(); |
1648 | } |
1649 | } |
1650 | |
1651 | /** |
1652 | * closes underlying connection and associated resource. |
1653 | */ |
1654 | synchronized public void closeX() throws SQLException { |
1655 | // call super.close*() to do the close* |
1656 | super.closeX(); |
1657 | if (!isXAConnection_) |
1658 | return; |
1659 | if (isOpen()) { |
1660 | return; // still open, return |
1661 | } |
1662 | if (xares_ != null) { |
1663 | xares_.removeXaresFromSameRMchain(); |
1664 | } |
1665 | } |
1666 | |
1667 | /** |
1668 | * Invalidates connection but keeps socket open. |
1669 | */ |
1670 | synchronized public void closeForReuse() throws SqlException { |
1671 | // call super.close*() to do the close* |
1672 | super.closeForReuse(); |
1673 | if (!isXAConnection_) |
1674 | return; |
1675 | if (isOpen()) { |
1676 | return; // still open, return |
1677 | } |
1678 | if (xares_ != null) { |
1679 | xares_.removeXaresFromSameRMchain(); |
1680 | } |
1681 | } |
1682 | |
1683 | /** |
1684 | * closes resources connection will be not available |
1685 | * for reuse. |
1686 | */ |
1687 | synchronized public void closeResources() throws SQLException { |
1688 | // call super.close*() to do the close* |
1689 | super.closeResources(); |
1690 | if (!isXAConnection_) |
1691 | return; |
1692 | |
1693 | if (isOpen()) { |
1694 | return; // still open, return |
1695 | } |
1696 | if (xares_ != null) { |
1697 | xares_.removeXaresFromSameRMchain(); |
1698 | } |
1699 | } |
1700 | |
1701 | |
1702 | /** |
1703 | * Invokes write commit on NetXAConnection |
1704 | */ |
1705 | protected void writeXACommit_() throws SqlException { |
1706 | xares_.netXAConn_.writeCommit(); |
1707 | } |
1708 | |
1709 | /** |
1710 | * Invokes readCommit on NetXAConnection |
1711 | */ |
1712 | protected void readXACommit_() throws SqlException { |
1713 | xares_.netXAConn_.readCommit(); |
1714 | } |
1715 | |
1716 | /** |
1717 | * Invokes writeRollback on NetXAConnection |
1718 | */ |
1719 | protected void writeXARollback_() throws SqlException { |
1720 | xares_.netXAConn_.writeRollback(); |
1721 | } |
1722 | |
1723 | /** |
1724 | * Invokes writeRollback on NetXAConnection |
1725 | */ |
1726 | protected void readXARollback_() throws SqlException { |
1727 | xares_.netXAConn_.readRollback(); |
1728 | } |
1729 | |
1730 | |
1731 | protected void writeXATransactionStart(Statement statement) throws SqlException { |
1732 | xares_.netXAConn_.writeTransactionStart(statement); |
1733 | } |
1734 | } |
1735 | |