001 /*
002
003 Derby - Class org.apache.derby.client.net.NetAgent
004
005 Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable.
006
007 Licensed under the Apache License, Version 2.0 (the "License");
008 you may not use this file except in compliance with the License.
009 You may obtain a copy of the License at
010
011 http://www.apache.org/licenses/LICENSE-2.0
012
013 Unless required by applicable law or agreed to in writing, software
014 distributed under the License is distributed on an "AS IS" BASIS,
015 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 See the License for the specific language governing permissions and
017 limitations under the License.
018
019 */
020
021 package org.apache.derby.client.net;
022
023 import org.apache.derby.client.am.Agent;
024 import org.apache.derby.client.am.DisconnectException;
025 import org.apache.derby.client.am.SqlException;
026 import org.apache.derby.client.am.Utils;
027
028 public class NetAgent extends Agent {
029 //---------------------navigational members-----------------------------------
030
031 // All these request objects point to the same physical request object.
032 public ConnectionRequestInterface connectionRequest_;
033 public NetConnectionRequest packageRequest_;
034 public StatementRequestInterface statementRequest_;
035 public ResultSetRequestInterface resultSetRequest_;
036
037 // All these reply objects point to the same physical reply object.
038 public ConnectionReply connectionReply_;
039 public ConnectionReply packageReply_;
040 public StatementReply statementReply_;
041 public ResultSetReply resultSetReply_;
042
043 //---------------------navigational cheat-links-------------------------------
044 // Cheat-links are for convenience only, and are not part of the conceptual model.
045 // Warning:
046 // Cheat-links should only be defined for invariant state data.
047 // That is, the state data is set by the constructor and never changes.
048
049 // Alias for (NetConnection) super.connection
050 NetConnection netConnection_;
051
052 // Alias for (Request) super.*Request, all in one
053 // In the case of the NET implementation, these all point to the same physical request object.
054 protected Request request_;
055 public NetConnectionRequest netConnectionRequest_;
056 public NetPackageRequest netPackageRequest_;
057 public NetStatementRequest netStatementRequest_;
058 public NetResultSetRequest netResultSetRequest_;
059
060 // Alias for (Reply) super.*Reply, all in one.
061 // In the case of the NET implementation, these all point to the same physical reply object.
062 protected Reply reply_;
063 public NetConnectionReply netConnectionReply_;
064 public NetPackageReply netPackageReply_;
065 public NetStatementReply netStatementReply_;
066 public NetResultSetReply netResultSetReply_;
067
068 //-----------------------------state------------------------------------------
069
070 java.net.Socket socket_;
071 java.io.InputStream rawSocketInputStream_;
072 java.io.OutputStream rawSocketOutputStream_;
073
074 String server_;
075 int port_;
076 public CcsidManager sourceCcsidManager_;
077 public CcsidManager targetCcsidManager_;
078 public Typdef typdef_;
079 public Typdef targetTypdef_;
080 public Typdef originalTargetTypdef_; // added to support typdef overrides
081
082 protected int svrcod_;
083
084 public int orignalTargetSqlam_ = NetConfiguration.MGRLVL_7;
085 public int targetSqlam_ = orignalTargetSqlam_;
086
087 public SqlException exceptionOpeningSocket_ = null;
088
089 //---------------------constructors/finalizer---------------------------------
090 public NetAgent(NetConnection netConnection,
091 org.apache.derby.client.am.LogWriter logWriter) throws SqlException {
092 super(netConnection, logWriter);
093 this.netConnection_ = netConnection;
094 }
095
096 NetAgent(NetConnection netConnection,
097 org.apache.derby.client.am.LogWriter netLogWriter,
098 int loginTimeout,
099 String server,
100 int port) throws SqlException {
101 super(netConnection, netLogWriter);
102
103 server_ = server;
104 port_ = port;
105 netConnection_ = netConnection;
106 if (server_ == null) {
107 throw new DisconnectException(this, "Required property \"serverName\" not set");
108 }
109
110 try {
111 socket_ = (java.net.Socket) java.security.AccessController.doPrivileged(new OpenSocketAction(server, port));
112 } catch (java.security.PrivilegedActionException e) {
113 throw new DisconnectException(this,
114 e.getClass().getName() + " : Error opening socket to server " + server + " on port " + port + " with message : " + e.getMessage());
115 }
116
117 // Set TCP/IP Socket Properties
118 try {
119 if (exceptionOpeningSocket_ == null) {
120 socket_.setTcpNoDelay(true); // disables nagles algorithm
121 socket_.setKeepAlive(true); // PROTOCOL Manual: TCP/IP connection allocation rule #2
122 socket_.setSoTimeout(loginTimeout * 1000);
123 }
124 } catch (java.net.SocketException e) {
125 try {
126 socket_.close();
127 } catch (java.io.IOException doNothing) {
128 }
129 exceptionOpeningSocket_ = new DisconnectException(this,
130 "SocketException '" + e.getMessage() + "'");
131 }
132
133 try {
134 if (exceptionOpeningSocket_ == null) {
135 rawSocketOutputStream_ = socket_.getOutputStream();
136 rawSocketInputStream_ = socket_.getInputStream();
137 }
138 } catch (java.io.IOException e) {
139 try {
140 socket_.close();
141 } catch (java.io.IOException doNothing) {
142 }
143 exceptionOpeningSocket_ = new DisconnectException(this, "unable to open stream on socket '"+e.getMessage() + "'");
144 }
145
146 sourceCcsidManager_ = new EbcdicCcsidManager(); // delete these
147 targetCcsidManager_ = sourceCcsidManager_; // delete these
148
149 if (netConnection_.isXAConnection()) {
150 NetXAConnectionReply netXAConnectionReply_ = new NetXAConnectionReply(this, netConnection_.commBufferSize_);
151 netResultSetReply_ = (NetResultSetReply) netXAConnectionReply_;
152 netStatementReply_ = (NetStatementReply) netResultSetReply_;
153 netPackageReply_ = (NetPackageReply) netStatementReply_;
154 netConnectionReply_ = (NetConnectionReply) netPackageReply_;
155 reply_ = (Reply) netConnectionReply_;
156
157 resultSetReply_ = new ResultSetReply(this,
158 netResultSetReply_,
159 netStatementReply_,
160 netConnectionReply_);
161 statementReply_ = (StatementReply) resultSetReply_;
162 packageReply_ = (ConnectionReply) statementReply_;
163 connectionReply_ = (ConnectionReply) packageReply_;
164 NetXAConnectionRequest netXAConnectionRequest_ = new NetXAConnectionRequest(this, sourceCcsidManager_, netConnection_.commBufferSize_);
165 netResultSetRequest_ = (NetResultSetRequest) netXAConnectionRequest_;
166 netStatementRequest_ = (NetStatementRequest) netResultSetRequest_;
167 netPackageRequest_ = (NetPackageRequest) netStatementRequest_;
168 netConnectionRequest_ = (NetConnectionRequest) netPackageRequest_;
169 request_ = (Request) netConnectionRequest_;
170
171 resultSetRequest_ = (ResultSetRequestInterface) netResultSetRequest_;
172 statementRequest_ = (StatementRequestInterface) netStatementRequest_;
173 packageRequest_ = (NetConnectionRequest) netPackageRequest_;
174 connectionRequest_ = (ConnectionRequestInterface) netConnectionRequest_;
175 } else {
176 netResultSetReply_ = new NetResultSetReply(this, netConnection_.commBufferSize_);
177 netStatementReply_ = (NetStatementReply) netResultSetReply_;
178 netPackageReply_ = (NetPackageReply) netStatementReply_;
179 netConnectionReply_ = (NetConnectionReply) netPackageReply_;
180 reply_ = (Reply) netConnectionReply_;
181
182 resultSetReply_ = new ResultSetReply(this,
183 netResultSetReply_,
184 netStatementReply_,
185 netConnectionReply_);
186 statementReply_ = (StatementReply) resultSetReply_;
187 packageReply_ = (ConnectionReply) statementReply_;
188 connectionReply_ = (ConnectionReply) packageReply_;
189 netResultSetRequest_ = new NetResultSetRequest(this, sourceCcsidManager_, netConnection_.commBufferSize_);
190 netStatementRequest_ = (NetStatementRequest) netResultSetRequest_;
191 netPackageRequest_ = (NetPackageRequest) netStatementRequest_;
192 netConnectionRequest_ = (NetConnectionRequest) netPackageRequest_;
193 request_ = (Request) netConnectionRequest_;
194
195 resultSetRequest_ = (ResultSetRequestInterface) netResultSetRequest_;
196 statementRequest_ = (StatementRequestInterface) netStatementRequest_;
197 packageRequest_ = (NetConnectionRequest) netPackageRequest_;
198 connectionRequest_ = (ConnectionRequestInterface) netConnectionRequest_;
199 }
200 }
201
202 protected void resetAgent_(org.apache.derby.client.am.LogWriter netLogWriter,
203 //CcsidManager sourceCcsidManager,
204 //CcsidManager targetCcsidManager,
205 int loginTimeout,
206 String server,
207 int port) throws SqlException {
208
209 // most properties will remain unchanged on connect reset.
210 targetTypdef_ = originalTargetTypdef_;
211 svrcod_ = 0;
212
213 // Set TCP/IP Socket Properties
214 try {
215 socket_.setSoTimeout(loginTimeout * 1000);
216 } catch (java.net.SocketException e) {
217 try {
218 socket_.close();
219 } catch (java.io.IOException doNothing) {
220 }
221 throw new SqlException(logWriter_, e, "SocketException '" + e.getMessage() + "'");
222 }
223 }
224
225
226 void setSvrcod(int svrcod) {
227 if (svrcod > svrcod_) {
228 svrcod_ = svrcod;
229 }
230 }
231
232 void clearSvrcod() {
233 svrcod_ = CodePoint.SVRCOD_INFO;
234 }
235
236 int getSvrcod() {
237 return svrcod_;
238 }
239
240 public void flush_() throws DisconnectException {
241 sendRequest();
242 reply_.initialize();
243 }
244
245 // Close socket and its streams.
246 public void close_() throws SqlException {
247 // can we just close the socket here, do we need to close streams individually
248 SqlException accumulatedExceptions = null;
249 if (rawSocketInputStream_ != null) {
250 try {
251 rawSocketInputStream_.close();
252 } catch (java.io.IOException e) {
253 // note when {6} = 0 it indicates the socket was closed.
254 // this should be ok since we are going to go an close the socket
255 // immediately following this call.
256 // changing {4} to e.getMessage() may require pub changes
257 accumulatedExceptions =
258 new SqlException(logWriter_, e, "A communication error has been detected. " +
259 "Communication protocol being used: {0}. " +
260 "Communication API being used: {1}. " +
261 "Location where the error was detected: {2}. " +
262 "Communication function detecting the error: {3}. " +
263 "Protocol specific error codes(s) {4}, {5}, {6}. " +
264 "TCP/IP " + "SOCKETS " + "Agent.close() " +
265 "InputStream.close() " + e.getMessage() + " " + "* " + "0");
266 //"08001",
267 //-30081);
268 } finally {
269 rawSocketInputStream_ = null;
270 }
271 }
272
273 if (rawSocketOutputStream_ != null) {
274 try {
275 rawSocketOutputStream_.close();
276 } catch (java.io.IOException e) {
277 // note when {6} = 0 it indicates the socket was closed.
278 // this should be ok since we are going to go an close the socket
279 // immediately following this call.
280 // changing {4} to e.getMessage() may require pub changes
281 SqlException latestException = new SqlException(logWriter_,
282 e,
283 "A communication error has been detected. " +
284 "Communication protocol being used: {0}. " +
285 "Communication API being used: {1}. " +
286 "Location where the error was detected: {2}. " +
287 "Communication function detecting the error: {3}. " +
288 "Protocol specific error codes(s) {4}, {5}, {6}. " +
289 "TCP/IP " + "SOCKETS " + "Agent.close() " +
290 "OutputStream.close() " + e.getMessage() + " " + "* " + "0");
291 accumulatedExceptions = Utils.accumulateSQLException(latestException, accumulatedExceptions);
292 } finally {
293 rawSocketOutputStream_ = null;
294 }
295 }
296
297 if (socket_ != null) {
298 try {
299 socket_.close();
300 } catch (java.io.IOException e) {
301 // again {6} = 0, indicates the socket was closed.
302 // maybe set {4} to e.getMessage().
303 // do this for now and but may need to modify or
304 // add this to the message pubs.
305 SqlException latestException = new SqlException(logWriter_,
306 e,
307 "A communication error has been detected. " +
308 "Communication protocol being used: {0}. " +
309 "Communication API being used: {1}. " +
310 "Location where the error was detected: {2}. " +
311 "Communication function detecting the error: {3}. " +
312 "Protocol specific error codes(s) {4}, {5}, {6}. " +
313 "TCP/IP " + "SOCKETS " + "Agent.close() " +
314 "Socket.close() " + e.getMessage() + " " + "* " + "0");
315 accumulatedExceptions = Utils.accumulateSQLException(latestException, accumulatedExceptions);
316 } finally {
317 socket_ = null;
318 }
319 }
320
321 if (accumulatedExceptions != null) {
322 throw accumulatedExceptions;
323 }
324 }
325
326
327 protected void sendRequest() throws DisconnectException {
328 try {
329 request_.flush(rawSocketOutputStream_);
330 } catch (java.io.IOException e) {
331 throwCommunicationsFailure("NetAgent.sendRequest()",
332 "OutputStream.flush()",
333 e.getMessage(),
334 "*");
335 }
336 }
337
338 public java.io.InputStream getInputStream() {
339 return rawSocketInputStream_;
340 }
341
342 public java.io.OutputStream getOutputStream() {
343 return rawSocketOutputStream_;
344 }
345
346 void setInputStream(java.io.InputStream inputStream) {
347 rawSocketInputStream_ = inputStream;
348 }
349
350 void setOutputStream(java.io.OutputStream outputStream) {
351 rawSocketOutputStream_ = outputStream;
352 }
353
354 public void throwCommunicationsFailure(String location,
355 String function,
356 String rc1,
357 String rc2) throws org.apache.derby.client.am.DisconnectException {
358 //org.apache.derby.client.am.DisconnectException
359 //accumulateReadExceptionAndDisconnect
360 // note when {6} = 0 it indicates the socket was closed.
361 // need to still validate any token values against message publications.
362 accumulateChainBreakingReadExceptionAndThrow(new org.apache.derby.client.am.DisconnectException(this,
363 "A communication error has been detected. " +
364 "Communication protocol being used: " + location + ". " +
365 "Communication API being used: " + function + ". " +
366 "Location where the error was detected: " + rc1 + ". " +
367 "Communication function detecting the error: " + rc2 + ". " +
368 "Protocol specific error codes(s) " +
369 "TCP/IP SOCKETS ")); // hardcode tokens 0 and 1
370 //"08001")); //derby code -30081, don't send 08001 now either
371 }
372
373 // ----------------------- call-down methods ---------------------------------
374
375 public org.apache.derby.client.am.LogWriter newLogWriter_(java.io.PrintWriter printWriter,
376 int traceLevel) {
377 return new NetLogWriter(printWriter, traceLevel);
378 }
379
380 protected void markChainBreakingException_() {
381 setSvrcod(CodePoint.SVRCOD_ERROR);
382 }
383
384 public void checkForChainBreakingException_() throws SqlException {
385 int svrcod = getSvrcod();
386 clearSvrcod();
387 if (svrcod > CodePoint.SVRCOD_WARNING) // Not for SQL warning, if svrcod > WARNING, then its a chain breaker
388 {
389 super.checkForExceptions(); // throws the accumulated exceptions, we'll always have at least one.
390 }
391 }
392
393 private void writeDeferredResetConnection() throws SqlException {
394 if (!netConnection_.resetConnectionAtFirstSql_) {
395 return;
396 }
397 try {
398 netConnection_.writeDeferredReset();
399 } catch (SqlException sqle) {
400 DisconnectException de = new DisconnectException(this, "An error occurred during a deferred connect reset and the connection has been terminated. See chained exceptions for details.");
401 de.setNextException(sqle);
402 throw de;
403 }
404 }
405
406 public void beginWriteChainOutsideUOW() throws SqlException {
407 request_.initialize();
408 writeDeferredResetConnection();
409 super.beginWriteChainOutsideUOW();
410 }
411
412 public void beginWriteChain(org.apache.derby.client.am.Statement statement) throws SqlException {
413 request_.initialize();
414 writeDeferredResetConnection();
415 super.beginWriteChain(statement);
416 }
417
418 protected void endWriteChain() {
419 super.endWriteChain();
420 }
421
422 private void readDeferredResetConnection() throws SqlException {
423 if (!netConnection_.resetConnectionAtFirstSql_) {
424 return;
425 }
426 try {
427 netConnection_.readDeferredReset();
428 checkForExceptions();
429 } catch (SqlException sqle) {
430 DisconnectException de = new DisconnectException(this, "An error occurred during a deferred connect reset and the connection has been terminated. See chained exceptions for details.");
431 de.setNextException(sqle);
432 throw de;
433 }
434 }
435
436 protected void beginReadChain(org.apache.derby.client.am.Statement statement) throws SqlException {
437 readDeferredResetConnection();
438 super.beginReadChain(statement);
439 }
440
441 protected void beginReadChainOutsideUOW() throws SqlException {
442 readDeferredResetConnection();
443 super.beginReadChainOutsideUOW();
444 }
445
446 public void endReadChain() throws SqlException {
447 super.endReadChain();
448 }
449
450
451 public String convertToStringTcpIpAddress(int tcpIpAddress) {
452 StringBuffer ipAddrBytes = new StringBuffer();
453 ipAddrBytes.append((tcpIpAddress >> 24) & 0xff);
454 ipAddrBytes.append(".");
455 ipAddrBytes.append((tcpIpAddress >> 16) & 0xff);
456 ipAddrBytes.append(".");
457 ipAddrBytes.append((tcpIpAddress >> 8) & 0xff);
458 ipAddrBytes.append(".");
459 ipAddrBytes.append((tcpIpAddress) & 0xff);
460
461 return ipAddrBytes.toString();
462 }
463
464 protected int getPort() {
465 return port_;
466 }
467
468 }
469
|