KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > drda > NetworkServerControlImpl


1 /*
2
3    Derby - Class org.apache.derby.impl.drda.NetworkServerControlImpl
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.impl.drda;
23
24 import java.io.ByteArrayInputStream JavaDoc;
25 import java.io.ByteArrayOutputStream JavaDoc;
26 import java.io.DataOutputStream JavaDoc;
27 import java.io.FilterOutputStream JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.InputStream JavaDoc;
30 import java.io.OutputStream JavaDoc;
31 import java.io.PrintStream JavaDoc;
32 import java.io.PrintWriter JavaDoc;
33 import java.net.InetAddress JavaDoc;
34 import java.net.ServerSocket JavaDoc;
35 import java.net.Socket JavaDoc;
36 import java.net.UnknownHostException JavaDoc;
37 import java.security.AccessController JavaDoc;
38 import java.security.PrivilegedActionException JavaDoc;
39 import java.security.PrivilegedExceptionAction JavaDoc;
40 import java.sql.Connection JavaDoc;
41 import java.sql.Driver JavaDoc;
42 import java.sql.DriverManager JavaDoc;
43 import java.sql.SQLException JavaDoc;
44 import java.sql.SQLWarning JavaDoc;
45 import java.util.ArrayList JavaDoc;
46 import java.util.Enumeration JavaDoc;
47 import java.util.Hashtable JavaDoc;
48 import java.util.Properties JavaDoc;
49 import java.util.StringTokenizer JavaDoc;
50 import java.util.Vector JavaDoc;
51
52 import org.apache.derby.drda.NetworkServerControl;
53 import org.apache.derby.iapi.error.StandardException;
54 import org.apache.derby.iapi.jdbc.DRDAServerStarter;
55 import org.apache.derby.iapi.reference.Attribute;
56 import org.apache.derby.iapi.reference.DRDAConstants;
57 import org.apache.derby.iapi.reference.Property;
58 import org.apache.derby.iapi.reference.SQLState;
59 import org.apache.derby.iapi.services.i18n.MessageService;
60 import org.apache.derby.iapi.services.info.JVMInfo;
61 import org.apache.derby.iapi.services.info.ProductGenusNames;
62 import org.apache.derby.iapi.services.info.ProductVersionHolder;
63 import org.apache.derby.iapi.services.monitor.Monitor;
64 import org.apache.derby.iapi.services.property.PropertyUtil;
65 import org.apache.derby.iapi.services.sanity.SanityManager;
66 import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
67 import org.apache.derby.iapi.tools.i18n.LocalizedResource;
68 import org.apache.derby.iapi.util.CheapDateFormatter;
69 import org.apache.derby.iapi.util.StringUtil;
70 import org.apache.derby.impl.jdbc.EmbedSQLException;
71
72 /**
73     
74     NetworkServerControlImpl does all the work for NetworkServerControl
75     @see NetworkServerControl for description
76
77 */

78 public final class NetworkServerControlImpl {
79     private final static int NO_USAGE_MSGS= 12;
80     private final static String JavaDoc [] COMMANDS =
81     {"start","shutdown","trace","tracedirectory","ping",
82      "logconnections", "sysinfo", "runtimeinfo", "maxthreads", "timeslice"};
83     // number of required arguments for each command
84
private final static int [] COMMAND_ARGS =
85     {0, 0, 1, 1, 0, 1, 0, 0, 1, 1};
86     private final static int COMMAND_START = 0;
87     private final static int COMMAND_SHUTDOWN = 1;
88     private final static int COMMAND_TRACE = 2;
89     private final static int COMMAND_TRACEDIRECTORY = 3;
90     private final static int COMMAND_TESTCONNECTION = 4;
91     private final static int COMMAND_LOGCONNECTIONS = 5;
92     private final static int COMMAND_SYSINFO = 6;
93     private final static int COMMAND_RUNTIME_INFO = 7;
94     private final static int COMMAND_MAXTHREADS = 8;
95     private final static int COMMAND_TIMESLICE = 9;
96     private final static int COMMAND_PROPERTIES = 10;
97     private final static int COMMAND_UNKNOWN = -1;
98     private final static String JavaDoc [] DASHARGS =
99     {"p","d","u","ld","ea","ep", "b", "h", "s"};
100     private final static int DASHARG_PORT = 0;
101     private final static int DASHARG_DATABASE = 1;
102     private final static int DASHARG_USER = 2;
103     private final static int DASHARG_LOADSYSIBM = 3;
104     private final static int DASHARG_ENCALG = 4;
105     private final static int DASHARG_ENCPRV = 5;
106     private final static int DASHARG_BOOTPASSWORD = 6;
107     private final static int DASHARG_HOST = 7;
108     private final static int DASHARG_SESSION = 8;
109
110     // command protocol version - you need to increase this number each time
111
// the command protocol changes
112
private final static int PROTOCOL_VERSION = 1;
113     private final static String JavaDoc COMMAND_HEADER = "CMD:";
114     private final static String JavaDoc REPLY_HEADER = "RPY:";
115     private final static int REPLY_HEADER_LENGTH = REPLY_HEADER.length();
116     private final static int OK = 0;
117     private final static int WARNING = 1;
118     private final static int ERROR = 2;
119     private final static int SQLERROR = 3;
120     private final static int SQLWARNING = 4;
121
122     private final static String JavaDoc DRDA_PROP_MESSAGES = "org.apache.derby.loc.drda.messages";
123     private final static String JavaDoc DRDA_PROP_DEBUG = "derby.drda.debug";
124     private final static String JavaDoc CLOUDSCAPE_DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";
125
126     public final static String JavaDoc UNEXPECTED_ERR = "Unexpected exception";
127
128     private final static int MIN_MAXTHREADS = -1;
129     private final static int MIN_TIMESLICE = -1;
130     private final static int USE_DEFAULT = -1;
131     private final static int DEFAULT_MAXTHREADS = 0; //for now create whenever needed
132
private final static int DEFAULT_TIMESLICE = 0; //for now never yield
133

134    private final static String JavaDoc DEFAULT_HOST = "localhost";
135     private final static String JavaDoc DRDA_MSG_PREFIX = "DRDA_";
136     private final static String JavaDoc DEFAULT_LOCALE= "en";
137     private final static String JavaDoc DEFAULT_LOCALE_COUNTRY="US";
138
139     // Check up to 10 seconds to see if shutdown occurred
140
private final static int SHUTDOWN_CHECK_ATTEMPTS = 20;
141     private final static int SHUTDOWN_CHECK_INTERVAL= 500;
142
143     // maximum reply size
144
private final static int MAXREPLY = 32767;
145
146     // Application Server Attributes.
147
protected static String JavaDoc att_srvclsnm;
148     protected final static String JavaDoc ATT_SRVNAM = "NetworkServerControl";
149
150     protected static String JavaDoc att_extnam;
151     protected static String JavaDoc att_srvrlslv;
152     protected static String JavaDoc prdId;
153     protected static byte[] prdIdBytes_;
154     
155     private static String JavaDoc buildNumber;
156     private static String JavaDoc versionString;
157     // we will use single or mixed, not double byte to reduce traffic on the
158
// wire, this is in keeping with JCC
159
// Note we specify UTF8 for the single byte encoding even though it can
160
// be multi-byte.
161
protected final static int CCSIDSBC = 1208; //use UTF8
162
protected final static int CCSIDMBC = 1208; //use UTF8
163
protected final static String JavaDoc DEFAULT_ENCODING = "UTF8"; // use UTF8 for writing
164
protected final static int DEFAULT_CCSID = 1208;
165     protected final static byte SPACE_CHAR = 32;
166                                                         
167
168     // Application Server manager levels - this needs to be in sync
169
// with CodePoint.MGR_CODEPOINTS
170
protected final static int [] MGR_LEVELS = { 7, // AGENT
171
4, // CCSID Manager
172
0, // CNMAPPC not implemented
173
0, // CMNSYNCPT not implemented
174
5, // CMNTCPIP
175
0, // DICTIONARY
176
7, // RDB
177
0, // RSYNCMGR
178
7, // SECMGR
179
7, // SQLAM
180
0, // SUPERVISOR
181
0, // SYNCPTMGR
182
7 // XAMGR
183
};
184                                             
185     
186     protected PrintWriter JavaDoc logWriter; // console
187
protected PrintWriter JavaDoc cloudscapeLogWriter; // derby.log
188
private static Driver JavaDoc cloudscapeDriver;
189
190     // error types
191
private final static int ERRTYPE_SEVERE = 1;
192     private final static int ERRTYPE_USER = 2;
193     private final static int ERRTYPE_INFO = 3;
194     private final static int ERRTYPE_UNKNOWN = -1;
195
196     // command argument information
197
private Vector JavaDoc commandArgs = new Vector JavaDoc();
198     private String JavaDoc databaseArg;
199     private String JavaDoc userArg;
200     private String JavaDoc passwordArg;
201     private String JavaDoc bootPasswordArg;
202     private String JavaDoc encAlgArg;
203     private String JavaDoc encPrvArg;
204     private String JavaDoc hostArg = DEFAULT_HOST;
205     private InetAddress JavaDoc hostAddress;
206     private int sessionArg;
207
208     // Used to debug memory in SanityManager.DEBUG mode
209
private memCheck mc;
210
211     // reply buffer
212
private byte [] replyBuffer;
213     private int replyBufferCount; //length of reply
214
private int replyBufferPos; //current position in reply
215

216     //
217
// server configuration
218
//
219
// static values - set at start can't be changed once server has started
220
private int portNumber = NetworkServerControl.DEFAULT_PORTNUMBER; // port server listens to
221

222     // configurable values
223
private String JavaDoc traceDirectory; // directory to place trace files in
224
private Object JavaDoc traceDirectorySync = new Object JavaDoc();// object to use for syncing
225
private boolean traceAll; // trace all sessions
226
private Object JavaDoc traceAllSync = new Object JavaDoc(); // object to use for syncing reading
227
// and changing trace all
228
private Object JavaDoc serverStartSync = new Object JavaDoc(); // for syncing start of server.
229
private boolean logConnections; // log connects
230
private Object JavaDoc logConnectionsSync = new Object JavaDoc(); // object to use for syncing
231
// logConnections value
232
private int minThreads; // default minimum number of connection threads
233
private int maxThreads; // default maximum number of connection threads
234
private Object JavaDoc threadsSync = new Object JavaDoc(); // object to use for syncing reading
235
// and changing default min and max threads
236
private int timeSlice; // default time slice of a session to a thread
237
private Object JavaDoc timeSliceSync = new Object JavaDoc();// object to use for syncing reading
238
// and changing timeSlice
239

240     private boolean keepAlive = true; // keepAlive value for client socket
241
private int minPoolSize; //minimum pool size for pooled connections
242
private int maxPoolSize; //maximum pool size for pooled connections
243
private Object JavaDoc poolSync = new Object JavaDoc(); // object to use for syning reading
244

245     protected boolean debugOutput = false;
246     private boolean cleanupOnStart = false; // Should we clean up when starting the server?
247
private boolean restartFlag = false;
248
249     protected final static int INVALID_OR_NOTSET_SECURITYMECHANISM = -1;
250     // variable to store value set to derby.drda.securityMechanism
251
// default value is -1 which indicates that this property isnt set or
252
// the value is invalid
253
private int allowOnlySecurityMechanism = INVALID_OR_NOTSET_SECURITYMECHANISM;
254     //
255
// variables for a client command session
256
//
257
private Socket JavaDoc clientSocket = null;
258     private InputStream JavaDoc clientIs = null;
259     private OutputStream JavaDoc clientOs = null;
260     private ByteArrayOutputStream JavaDoc byteArrayOs = new ByteArrayOutputStream JavaDoc();
261     private DataOutputStream JavaDoc commandOs = new DataOutputStream JavaDoc(byteArrayOs);
262     
263     private Object JavaDoc shutdownSync = new Object JavaDoc();
264     private boolean shutdown;
265     private int connNum; // number of connections since server started
266
private ServerSocket JavaDoc serverSocket;
267     private NetworkServerControlImpl serverInstance;
268     private LocalizedResource langUtil;
269     public String JavaDoc clientLocale;
270     ArrayList JavaDoc localAddresses; // list of local addresses for checking admin
271
// commands.
272

273     // open sessions
274
private Hashtable JavaDoc sessionTable = new Hashtable JavaDoc();
275
276     // current session
277
private Session currentSession;
278     // DRDAConnThreads
279
private Vector JavaDoc threadList = new Vector JavaDoc();
280
281     // queue of sessions waiting for a free thread - the queue is managed
282
// in a simple first come, first serve manner - no priorities
283
private Vector JavaDoc runQueue = new Vector JavaDoc();
284
285     // number of DRDAConnThreads waiting for something to do
286
private int freeThreads;
287
288     // known application requesters
289
private Hashtable JavaDoc appRequesterTable = new Hashtable JavaDoc();
290
291     // accessed by inner classes for privileged action
292
private String JavaDoc propertyFileName;
293     private Runnable JavaDoc acceptClients;
294     
295
296     // if the server is started from the command line, it should shutdown the
297
// databases it has booted.
298
private boolean shutdownDatabasesOnShutdown = false;
299     
300     /**
301      * Can EUSRIDPWD security mechanism be used with
302      * the current JVM
303      */

304     private static boolean SUPPORTS_EUSRIDPWD = false;
305
306     /*
307      * DRDA Specification for the EUSRIDPWD security mechanism
308      * requires DH algorithm support with a 32-byte prime to be
309      * used. Not all JCE implementations have support for this.
310      * Hence here we need to find out if EUSRIDPWD can be used
311      * with the current JVM.
312      */

313     static
314     {
315         try
316         {
317             // The DecryptionManager class will instantiate objects of the required
318
// security algorithms that are needed for EUSRIDPWD
319
// An exception will be thrown if support is not available
320
// in the JCE implementation in the JVM in which the server
321
// is started.
322
new DecryptionManager();
323             SUPPORTS_EUSRIDPWD = true;
324         }catch(Exception JavaDoc e)
325         {
326             // if an exception is thrown, ignore exception.
327
// set SUPPORTS_EUSRIDPWD to false indicating that the server
328
// does not have support for EUSRIDPWD security mechanism
329
SUPPORTS_EUSRIDPWD = false;
330         }
331     }
332
333     // constructor
334
public NetworkServerControlImpl() throws Exception JavaDoc
335     {
336         init();
337         getPropertyInfo();
338     }
339
340
341     /**
342      * Internal constructor for NetworkServerControl API.
343      * @param address - InetAddress to listen on, May not be null. Throws NPE if null
344      * @param portNumber - portNumber to listen on, -1 use propert or default.
345      * @throws Exception on error
346      * @see NetworkServerControl
347      */

348     public NetworkServerControlImpl(InetAddress JavaDoc address, int portNumber) throws Exception JavaDoc
349     {
350         init();
351         getPropertyInfo();
352         this.hostAddress = address;
353         this.portNumber = (portNumber <= 0) ?
354             this.portNumber: portNumber;
355         this.hostArg = address.getHostAddress();
356     }
357
358     private void init() throws Exception JavaDoc
359     {
360
361         // adjust the application in accordance with derby.ui.locale and derby.ui.codeset
362
langUtil = new LocalizedResource(null,null,DRDA_PROP_MESSAGES);
363
364         serverInstance = this;
365         
366         //set Server attributes to be used in EXCSAT
367
ProductVersionHolder myPVH = getNetProductVersionHolder();
368         att_extnam = ATT_SRVNAM + " " + java.lang.Thread.currentThread().getName();
369         
370         att_srvclsnm = myPVH.getProductName();
371         versionString = myPVH.getVersionBuildString(true);
372         
373         String JavaDoc majorStr = String.valueOf(myPVH.getMajorVersion());
374         String JavaDoc minorStr = String.valueOf(myPVH.getMinorVersion());
375         // Maintenance version. Server protocol version.
376
// Only changed if client needs to recognize a new server version.
377
String JavaDoc drdaMaintStr = String.valueOf(myPVH.getDrdaMaintVersion());
378
379         // PRDID format as JCC expects it: CSSMMmx
380
// MM = major version
381
// mm = minor version
382
// x = drda MaintenanceVersion
383

384         prdId = DRDAConstants.DERBY_DRDA_SERVER_ID;
385         if (majorStr.length() == 1)
386             prdId += "0";
387         prdId += majorStr;
388
389         if (minorStr.length() == 1)
390             prdId += "0";
391
392         prdId += minorStr;
393         
394         prdId += drdaMaintStr;
395         att_srvrlslv = prdId + "/" + myPVH.getVersionBuildString(true);
396                 // Precompute this to save some cycles
397
prdIdBytes_ = prdId.getBytes(DEFAULT_ENCODING);
398  
399         if (SanityManager.DEBUG)
400         {
401             if (majorStr.length() > 2 ||
402                 minorStr.length() > 2 ||
403                 drdaMaintStr.length() > 1)
404                 SanityManager.THROWASSERT("version values out of expected range for PRDID");
405         }
406
407         buildNumber = myPVH.getBuildNumber();
408     }
409
410     private PrintWriter JavaDoc makePrintWriter( OutputStream JavaDoc out)
411     {
412         if (out != null)
413             return new PrintWriter JavaDoc(out, true /* flush the buffer at the end of each line */);
414         else
415             return null;
416     }
417
418     protected static Driver JavaDoc getDriver()
419     {
420         return cloudscapeDriver;
421     }
422     
423
424     /********************************************************************************
425      * Implementation of NetworkServerControl API
426      * The server commands throw exceptions for errors, so that users can handle
427      * them themselves in addition to having the errors written to the console
428      * and possibly derby.log. To turn off logging the errors to the console,
429      * set the output writer to null.
430      ********************************************************************************/

431
432
433     /**
434      * Set the output stream for console messages
435      * If this is set to null, no messages will be written to the console
436      *
437      * @param outWriter output stream for console messages
438      */

439     public void setLogWriter(PrintWriter JavaDoc outWriter)
440     {
441         // wrap the user-set outWriter with, autoflush to true.
442
// this will ensure that messages to console will be
443
// written out to the outWriter on a println.
444
// DERBY-1466
445
if ( outWriter != null )
446             logWriter = new PrintWriter JavaDoc(outWriter,true);
447         else
448             logWriter = outWriter;
449     }
450
451
452     
453     /**
454      * Write an error message to console output stream
455      * and throw an exception for this error
456      *
457      * @param msg error message
458      * @exception Exception
459      */

460     public void consoleError(String JavaDoc msg)
461         throws Exception JavaDoc
462     {
463         consoleMessage(msg);
464         throw new Exception JavaDoc(msg);
465     }
466
467     /**
468      * Write an exception to console output stream,
469      * but only if debugOutput is true.
470      *
471      * @param e exception
472      */

473     public void consoleExceptionPrint(Exception JavaDoc e)
474     {
475         if (debugOutput == true)
476             consoleExceptionPrintTrace(e);
477
478         return;
479     }
480
481     /**
482      * Write an exception (with trace) to console
483      * output stream.
484      *
485      * @param e exception
486      */

487     public void consoleExceptionPrintTrace(Throwable JavaDoc e)
488     {
489         consoleMessage(e.getMessage());
490         if (logWriter != null)
491         {
492             synchronized (logWriter) {
493                 e.printStackTrace(logWriter);
494             }
495         }
496         else
497         {
498             e.printStackTrace();
499         }
500         
501         if (cloudscapeLogWriter != null)
502         {
503             synchronized(cloudscapeLogWriter) {
504                 e.printStackTrace(cloudscapeLogWriter);
505             }
506         }
507     }
508
509
510
511
512     /**
513      * Write a message to console output stream
514      *
515      * @param msg message
516      */

517     public void consoleMessage(String JavaDoc msg)
518     {
519         // print to console if we have one
520
if (logWriter != null)
521         {
522             synchronized(logWriter) {
523                 logWriter.println(msg);
524             }
525         }
526         // always print to derby.log
527
if (cloudscapeLogWriter != null)
528             synchronized(cloudscapeLogWriter)
529             {
530                 Monitor.logMessage(msg);
531             }
532     }
533
534
535
536     /**
537      * Start a network server. Launches a separate thread with
538      * DRDAServerStarter. Want to use Monitor.startModule,
539      * so it can all get shutdown when cloudscape shuts down, but
540      * can't get it working right now.
541      *
542      * @param consoleWriter PrintWriter to which server console will be
543      * output. Null will disable console output.
544      *
545      *
546      * @exception Exception throws an exception if an error occurs
547      */

548     public void start(PrintWriter JavaDoc consoleWriter)
549         throws Exception JavaDoc
550     {
551         DRDAServerStarter starter = new DRDAServerStarter();
552         starter.setStartInfo(hostAddress,portNumber,consoleWriter);
553         startNetworkServer();
554         starter.boot(false,null);
555     }
556
557
558     /**
559      * Start a network server
560      *
561      * @param consoleWriter PrintWriter to which server console will be
562      * output. Null will disable console output.
563      *
564      *
565      * @exception Exception throws an exception if an error occurs
566      */

567     public void blockingStart(PrintWriter JavaDoc consoleWriter)
568         throws Exception JavaDoc
569     {
570         startNetworkServer();
571         setLogWriter(consoleWriter);
572         cloudscapeLogWriter = Monitor.getStream().getPrintWriter();
573         if (SanityManager.DEBUG && debugOutput)
574         {
575             memCheck.showmem();
576             mc = new memCheck(200000);
577             mc.start();
578         }
579         // Open a server socket listener
580
try{
581             serverSocket = (ServerSocket JavaDoc) AccessController.doPrivileged(
582                                 new PrivilegedExceptionAction JavaDoc() {
583                                         public Object JavaDoc run() throws IOException JavaDoc,UnknownHostException JavaDoc
584                                         {
585                                             if (hostAddress == null)
586                                                 hostAddress = InetAddress.getByName(hostArg);
587                                             // Make a list of valid
588
// InetAddresses for NetworkServerControl
589
// admin commands.
590
buildLocalAddressList(hostAddress);
591                                             return new ServerSocket JavaDoc(portNumber
592                                                                     ,0,
593                                                                     hostAddress);
594                                         }
595                                     }
596                                 );
597         } catch (PrivilegedActionException JavaDoc e) {
598             Exception JavaDoc e1 = e.getException();
599             if (e1 instanceof IOException JavaDoc)
600                 consolePropertyMessage("DRDA_ListenPort.S",
601                                        new String JavaDoc [] {
602                                            Integer.toString(portNumber),
603                                            hostArg});
604             if (e1 instanceof UnknownHostException JavaDoc) {
605                 consolePropertyMessage("DRDA_UnknownHost.S", hostArg);
606             }
607             else
608                 throw e1;
609         } catch (Exception JavaDoc e) {
610         // If we find other (unexpected) errors, we ultimately exit--so make
611
// sure we print the error message before doing so (Beetle 5033).
612
throwUnexpectedException(e);
613         }
614         
615         consolePropertyMessage("DRDA_Ready.I", new String JavaDoc []
616                     {Integer.toString(portNumber), att_srvclsnm, versionString,
617                     getFormattedTimestamp()});
618         
619         // We accept clients on a separate thread so we don't run into a problem
620
// blocking on the accept when trying to process a shutdown
621
acceptClients = (Runnable JavaDoc)new ClientThread(this, serverSocket);
622         Thread JavaDoc clientThread = (Thread JavaDoc) AccessController.doPrivileged(
623                                 new PrivilegedExceptionAction JavaDoc() {
624                                     public Object JavaDoc run() throws Exception JavaDoc
625                                     {
626                                         return new Thread JavaDoc(acceptClients);
627                                     }
628                                 }
629                             );
630         clientThread.start();
631             
632         // wait until we are told to shutdown or someone sends an InterruptedException
633
synchronized(shutdownSync) {
634             try {
635                 shutdownSync.wait();
636             }
637             catch (InterruptedException JavaDoc e)
638             {
639                 shutdown = true;
640             }
641         }
642
643         // Need to interrupt the memcheck thread if it is sleeping.
644
if (mc != null)
645             mc.interrupt();
646
647         //interrupt client thread
648
clientThread.interrupt();
649
650         // Close out the sessions
651
synchronized(sessionTable) {
652             for (Enumeration JavaDoc e = sessionTable.elements(); e.hasMoreElements(); )
653             {
654                 Session session = (Session) e.nextElement();
655                 session.close();
656             }
657         }
658
659         synchronized (threadList)
660         {
661             //interupt any connection threads still active
662
for (int i = 0; i < threadList.size(); i++)
663             {
664                 ((DRDAConnThread)threadList.get(i)).close();
665                 ((DRDAConnThread)threadList.get(i)).interrupt();
666             }
667             threadList.clear();
668         }
669        
670  
671
672     
673         // close the listener socket
674
try{
675            serverSocket.close();
676         }catch(IOException JavaDoc e){
677             consolePropertyMessage("DRDA_ListenerClose.S");
678         }
679
680
681         // Wake up those waiting on sessions, so
682
// they can close down
683
synchronized (runQueue) {
684             runQueue.notifyAll();
685         }
686
687         if (shutdownDatabasesOnShutdown) {
688
689             // Shutdown Cloudscape
690
try {
691                 if (cloudscapeDriver != null)
692                     cloudscapeDriver.connect("jdbc:derby:;shutdown=true",
693                                              (Properties JavaDoc) null);
694             } catch (SQLException JavaDoc sqle) {
695                 // If we can't shutdown cloudscape. Perhaps authentication is
696
// set to true or some other reason. We will just print a
697
// message to the console and proceed.
698
String JavaDoc expectedState =
699                     StandardException.getSQLStateFromIdentifier(
700                             SQLState.CLOUDSCAPE_SYSTEM_SHUTDOWN);
701                 if (!expectedState.equals(sqle.getSQLState())) {
702                     consolePropertyMessage("DRDA_ShutdownWarning.I",
703                                            sqle.getMessage());
704                 }
705             }
706         }
707
708         consolePropertyMessage("DRDA_ShutdownSuccess.I", new String JavaDoc []
709                                 {att_srvclsnm, versionString,
710                                 getFormattedTimestamp()});
711         
712
713     }
714     
715     /**
716      * Load Cloudscape and save driver for future use.
717      * We can't call Driver Manager when the client connects,
718      * because they might be holding the DriverManager lock.
719      *
720      *
721      */

722
723     
724
725
726     protected void startNetworkServer() throws Exception JavaDoc
727     {
728
729         // we start the cloudscape server here.
730
boolean restartCheck = this.restartFlag;
731         synchronized (serverStartSync) {
732
733             if (restartCheck == this.restartFlag) {
734             // then we can go ahead and restart the server (odds
735
// that some else has just done so are very slim (but not
736
// impossible--however, even if it does happen, things
737
// should still work correctly, just not as efficiently...))
738

739                 try {
740     
741                     if (cleanupOnStart) {
742                     // we're restarting the server (probably after a shutdown
743
// exception), so we need to clean up first.
744

745                         // Close and remove sessions on runQueue.
746
synchronized (runQueue) {
747                             for (int i = 0; i < runQueue.size(); i++) {
748                                 Session s = (Session) runQueue.get(i);
749                                 s.close();
750                                 removeFromSessionTable(s.getConnNum());
751                             }
752                             runQueue.clear();
753                         }
754
755                         // DERBY-1326: There could be active threads that
756
// contain old/invalid sessions. These sessions won't
757
// be cleaned up until there is some activity on
758
// them. We could optimize this by going through
759
// sessionTable and closing the sessions' socket
760
// streams.
761

762                         // Unload driver, then restart the server.
763
cloudscapeDriver = null; // so it gets collected.
764
System.gc();
765                     }
766
767                     // start the server.
768
Class.forName(CLOUDSCAPE_DRIVER).newInstance();
769                     cloudscapeDriver = DriverManager.getDriver(Attribute.PROTOCOL);
770
771                 }
772                 catch (Exception JavaDoc e) {
773                     consolePropertyMessage("DRDA_LoadException.S", e.getMessage());
774                 }
775                 cleanupOnStart = true;
776                 this.restartFlag = !this.restartFlag;
777             }
778             // else, multiple threads hit this synchronize block at the same
779
// time, but one of them already executed it--so all others just
780
// return and do nothing (no need to restart the server multiple
781
// times in a row).
782
}
783     }
784
785     /**
786      * Shutdown a network server
787      *
788      * @exception Exception throws an exception if an error occurs
789      */

790     public void shutdown()
791         throws Exception JavaDoc
792     {
793         setUpSocket();
794         writeCommandHeader(COMMAND_SHUTDOWN);
795         send();
796         readResult();
797         // Wait up to 10 seconds for things to really shut down
798
// need a quiet ping so temporarily disable the logwriter
799
PrintWriter JavaDoc savWriter = logWriter;
800         // DERBY-1571: If logWriter is null, stack traces are printed to
801
// System.err. Set logWriter to a silent stream to suppress stack
802
// traces too.
803
FilterOutputStream JavaDoc silentStream = new FilterOutputStream JavaDoc(null) {
804                 public void write(int b) { }
805                 public void flush() { }
806                 public void close() { }
807             };
808         setLogWriter(new PrintWriter JavaDoc(silentStream));
809         int ntry;
810         for (ntry = 0; ntry < SHUTDOWN_CHECK_ATTEMPTS; ntry++)
811         {
812             Thread.sleep(SHUTDOWN_CHECK_INTERVAL);
813             try {
814                 ping();
815             } catch (Exception JavaDoc e)
816             {
817                 // as soon as we can't ping return
818
if (ntry == SHUTDOWN_CHECK_ATTEMPTS)
819                     consolePropertyMessage("DRDA_ShutdownError.S", new String JavaDoc [] {
820                         Integer.toString(portNumber),
821                         hostArg});
822                 break;
823             }
824         }
825         logWriter= savWriter;
826         return;
827     }
828
829     /*
830      Shutdown the server directly (If you have the original object)
831      No Network communication needed.
832     */

833     public void directShutdown() {
834         shutdown = true;
835         synchronized(shutdownSync) {
836             // wake up the server thread
837
shutdownSync.notifyAll();
838         }
839         
840     }
841
842
843     /**
844      */

845     public boolean isServerStarted() throws Exception JavaDoc
846     {
847         try {
848             ping();
849         }
850         catch (Exception JavaDoc e) {
851             return false;
852         }
853         return true;
854     }
855
856     public void ping() throws Exception JavaDoc
857     {
858         // database no longer used, but don't change the protocol
859
// in case we add
860
// authorization later.
861
String JavaDoc database = null; // no longer used but don't change the protocol
862
String JavaDoc user = null;
863         String JavaDoc password = null;
864
865             setUpSocket();
866             writeCommandHeader(COMMAND_TESTCONNECTION);
867             writeLDString(database);
868             writeLDString(user);
869             writeLDString(password);
870             send();
871             readResult();
872
873     }
874
875
876     /**
877      * Turn tracing on or off for all sessions
878      *
879      * @param on true to turn tracing on, false to turn tracing off
880      *
881      * @exception Exception throws an exception if an error occurs
882      */

883     public void trace(boolean on)
884         throws Exception JavaDoc
885     {
886         trace(0, on);
887     }
888
889     /**
890      * Turn tracing on or off for one session or all sessions
891      *
892      * @param connNum the connNum of the session, 0 if all sessions
893      * @param on true to turn tracing on, false to turn tracing off
894      *
895      * @exception Exception throws an exception if an error occurs
896      */

897     public void trace(int connNum, boolean on)
898         throws Exception JavaDoc
899     {
900         setUpSocket();
901         writeCommandHeader(COMMAND_TRACE);
902         commandOs.writeInt(connNum);
903         writeByte(on ? 1 : 0);
904         send();
905         readResult();
906         consoleTraceMessage(connNum, on);
907     }
908
909     /**
910      * Print trace change message to console
911      *
912      * @param on true to print tracing on, false to print tracing off
913      *
914      * @exception Exception throws an exception if an error occurs
915      */

916     private void consoleTraceMessage(int connNum, boolean on)
917         throws Exception JavaDoc
918     {
919         if (connNum == 0)
920             consolePropertyMessage("DRDA_TraceChangeAll.I", on ? "DRDA_ON.I" : "DRDA_OFF.I");
921         else
922         {
923             String JavaDoc[] args = new String JavaDoc[2];
924             args[0] = on ? "DRDA_ON.I" : "DRDA_OFF.I";
925             args[1] = new Integer JavaDoc(connNum).toString();
926             consolePropertyMessage("DRDA_TraceChangeOne.I", args);
927         }
928     }
929
930     /**
931      * Turn logging connections on or off. When logging is turned on a message is
932      * written to derby.log each time a connection is made.
933      *
934      * @param on true to turn on, false to turn off
935      *
936      * @exception Exception throws an exception if an error occurs
937      */

938     public void logConnections(boolean on)
939         throws Exception JavaDoc
940     {
941         setUpSocket();
942         writeCommandHeader(COMMAND_LOGCONNECTIONS);
943         writeByte(on ? 1 : 0);
944         send();
945         readResult();
946     }
947
948     /**
949      *@see NetworkServerControl#setTraceDirectory
950      */

951     public void sendSetTraceDirectory(String JavaDoc traceDirectory)
952         throws Exception JavaDoc
953     {
954         setUpSocket();
955         writeCommandHeader(COMMAND_TRACEDIRECTORY);
956         writeLDString(traceDirectory);
957         send();
958         readResult();
959     }
960
961     /**
962      *@see NetworkServerControl#getSysinfo
963      */

964     public String JavaDoc sysinfo()
965         throws Exception JavaDoc
966     {
967         setUpSocket();
968         writeCommandHeader(COMMAND_SYSINFO);
969         send();
970         return readStringReply("DRDA_SysInfoError.S");
971     }
972
973     /**
974      *@see NetworkServerControl#getRuntimeInfo
975      */

976     public String JavaDoc runtimeInfo()
977     throws Exception JavaDoc
978     {
979         setUpSocket();
980         writeCommandHeader(COMMAND_RUNTIME_INFO);
981         send();
982         return readStringReply("DRDA_RuntimeInfoError.S");
983     }
984
985     /**
986      * Display usage information
987      *
988      */

989     public void usage()
990     {
991         try {
992         for (int i = 1; i <= NO_USAGE_MSGS; i++)
993             consolePropertyMessage("DRDA_Usage"+i+".I");
994         } catch (Exception JavaDoc e) {} // ignore exceptions - there shouldn't be any
995
}
996
997     /**
998      * Connect to network server and set connection maxthread parameter
999      *
1000     * @param max maximum number of connections, if 0, connections
1001     * created when no free connection available
1002     * if -1, use default
1003     *
1004     * @exception Exception throws an exception if an error occurs
1005     */

1006    public void netSetMaxThreads(int max) throws Exception JavaDoc
1007    {
1008        setUpSocket();
1009        writeCommandHeader(COMMAND_MAXTHREADS);
1010        commandOs.writeInt(max);
1011        send();
1012        readResult();
1013        int newval = readInt();
1014        consolePropertyMessage("DRDA_MaxThreadsChange.I",
1015                    new Integer JavaDoc(newval).toString());
1016    }
1017
1018    /**
1019     * Set network server connection timeslice parameter
1020     *
1021     * @param timeslice amount of time given to each session before yielding to
1022     * another session, if 0, never yield. if -1, use default.
1023     *
1024     * @exception Exception throws an exception if an error occurs
1025     */

1026    public void netSetTimeSlice(int timeslice)
1027        throws Exception JavaDoc
1028    {
1029        setUpSocket();
1030        writeCommandHeader(COMMAND_TIMESLICE);
1031        commandOs.writeInt(timeslice);
1032        send();
1033        readResult();
1034        int newval = readInt();
1035        consolePropertyMessage("DRDA_TimeSliceChange.I",
1036                                       new Integer JavaDoc(newval).toString());
1037    }
1038
1039    /**
1040     * Get current properties
1041     *
1042     * @return Properties object containing properties
1043     * @exception Exception throws an exception if an error occurs
1044     */

1045    public Properties JavaDoc getCurrentProperties()
1046        throws Exception JavaDoc
1047    {
1048        setUpSocket();
1049        writeCommandHeader(COMMAND_PROPERTIES);
1050        send();
1051        byte [] val = readBytesReply("DRDA_PropertyError.S");
1052        Properties JavaDoc p = new Properties JavaDoc();
1053        try {
1054            ByteArrayInputStream JavaDoc bs = new ByteArrayInputStream JavaDoc(val);
1055            p.load(bs);
1056        } catch (IOException JavaDoc io) {
1057            consolePropertyMessage("DRDA_IOException.S",
1058                        io.getMessage());
1059        }
1060        return p;
1061    }
1062
1063    /**
1064     * Set a thread name to be something that is both meaningful and unique (primarily
1065     * for debugging purposes).
1066     *
1067     * The received thread's name is set to a new string of the form
1068     * [newName + "_n"], where 'n' is a unique thread id originally generated
1069     * by the jvm Thread constructor. If the default name of the thread has
1070     * been changed before getting here, then nothing is done.
1071     *
1072     * @param thrd An instance of a Thread object that still has its default
1073     * thread name (as generated by the jvm Thread constructor). This should
1074     * always be of the form "Thread-N", where N is a unique thread id
1075     * generated by the jvm. Ex. "Thread-0", "Thread-1", etc.
1076     *
1077     **/

1078    public static void setUniqueThreadName(Thread JavaDoc thrd, String JavaDoc newName) {
1079
1080        // First, pull off the unique thread id already found in thrd's default name;
1081
// we do so by searching for the '-' character, and then counting everything
1082
// after it as a N.
1083
if (thrd.getName().indexOf("Thread-") == -1) {
1084        // default name has been changed; don't do anything.
1085
return;
1086        }
1087        else {
1088            String JavaDoc oldName = thrd.getName();
1089            thrd.setName(newName + "_" +
1090              oldName.substring(oldName.indexOf("-")+1, oldName.length()));
1091        } // end else.
1092

1093        return;
1094
1095    }
1096
1097    /*******************************************************************************/
1098    /* Protected methods */
1099    /*******************************************************************************/
1100    /**
1101     * Remove session from session table
1102     *
1103     * @param sessionid id of session to be removed
1104     */

1105    protected void removeFromSessionTable(int sessionid)
1106    {
1107        sessionTable.remove(new Integer JavaDoc(sessionid));
1108    }
1109
1110    /**
1111     * processCommands reads and processes NetworkServerControlImpl commands sent
1112     * to the network server over the socket. The protocol used is
1113     * 4 bytes - String CMD:
1114     * 2 bytes - Protocol version
1115     * 1 byte - length of locale (0 for default)
1116     * n bytes - locale
1117     * 1 byte - length of codeset (0 for default)
1118     * n bytes - codeset
1119     * 1 byte - command
1120     * n bytes - parameters for the command
1121     * The server returns
1122     * 4 bytes - String RPY:
1123     * for most commands
1124     * 1 byte - command result, 0 - OK, 1 - warning, 2 - error
1125     * if warning or error
1126     * 1 bytes - length of message key
1127     * n bytes - message key
1128     * 1 byte - number of parameters to message
1129     * {2 bytes - length of parameter
1130     * n bytes - parameter} for each parameter
1131     * for sysinfo
1132     * 1 byte - command result, 0 - OK, 1 - warning, 2 - error
1133     * if OK
1134     * 2 bytes - length of sysinfo
1135     * n bytes - sysinfo
1136     *
1137     *
1138     * Note, the 3rd byte of the command must not be 'D0' to distinquish it
1139     * from DSS structures.
1140     * The protocol for the parameters for each command follows:
1141     *
1142     * Command: trace <connection id> {on | off}
1143     * Protocol:
1144     * 4 bytes - connection id - connection id of 0 means all sessions
1145     * 1 byte - 0 off, 1 on
1146     *
1147     * Command: logConnections {on | off}
1148     * Protocol:
1149     * 1 byte - 0 off, 1 on
1150     *
1151     * Command: shutdown
1152     * No parameters
1153     *
1154     * Command: sysinfo
1155     * No parameters
1156     *
1157     * Command: dbstart
1158     * Protocol:
1159     * 2 bytes - length of database name
1160     * n bytes - database name
1161     * 2 bytes - length of boot password
1162     * n bytes - boot password
1163     * 2 bytes - length of encryption algorithm
1164     * n bytes - encryption algorithm
1165     * 2 bytes - length of encryption provider
1166     * n bytes - encryption provider
1167     * 2 bytes - length of user name
1168     * n bytes - user name
1169     * 2 bytes - length of password
1170     * n bytes - password
1171     *
1172     * Command: dbshutdown
1173     * Protocol:
1174     * 2 bytes - length of database name
1175     * n bytes - database name
1176     * 2 bytes - length of user name
1177     * n bytes - user name
1178     * 2 bytes - length of password
1179     * n bytes - password
1180     *
1181     * Command: connpool
1182     * Protocol:
1183     * 2 bytes - length of database name, if 0, default for all databases
1184     * is set
1185     * n bytes - database name
1186     * 2 bytes - minimum number of connections, if 0, connection pool not used
1187     * if value is -1 use default
1188     * 2 bytes - maximum number of connections, if 0, connections are created
1189     * as needed, if value is -1 use default
1190     *
1191     * Command: maxthreads
1192     * Protocol:
1193     * 2 bytes - maximum number of threads
1194     *
1195     * Command: timeslice
1196     * Protocol:
1197     * 4 bytes - timeslice value
1198     *
1199     * Command: tracedirectory
1200     * Protocol:
1201     * 2 bytes - length of directory name
1202     * n bytes - directory name
1203     *
1204     * Command: test connection
1205     * Protocol:
1206     * 2 bytes - length of database name if 0, just the connection
1207     * to the network server is tested and user name and
1208     * password aren't sent
1209     * n bytes - database name
1210     * 2 bytes - length of user name (optional)
1211     * n bytes - user name
1212     * 2 bytes - length of password (optional)
1213     * n bytes - password
1214     *
1215     * The calling routine is synchronized so that multiple threads don't clobber each
1216     * other. This means that configuration commands will be serialized.
1217     * This shouldn't be a problem since they should be fairly rare.
1218     *
1219     * @param reader input reader for command
1220     * @param writer output writer for command
1221     * @param session session information
1222     *
1223     * @exception Throwable throws an exception if an error occurs
1224     */

1225    protected synchronized void processCommands(DDMReader reader, DDMWriter writer,
1226        Session session) throws Throwable JavaDoc
1227    {
1228        try {
1229            String JavaDoc protocolStr = reader.readCmdString(4);
1230            String JavaDoc locale = DEFAULT_LOCALE;
1231            String JavaDoc codeset = null;
1232            // get the version
1233
int version = reader.readNetworkShort();
1234            if (version <= 0 || version > PROTOCOL_VERSION)
1235                throw new Throwable JavaDoc(langUtil.getTextMessage("DRDA_UnknownProtocol.S", new Integer JavaDoc(version).toString()));
1236            int localeLen = reader.readByte();
1237            if (localeLen > 0)
1238            {
1239                currentSession = session;
1240                locale = reader.readCmdString(localeLen);
1241                session.langUtil = new LocalizedResource(codeset,locale,DRDA_PROP_MESSAGES);
1242            }
1243            String JavaDoc notLocalMessage = null;
1244            // for now codesetLen is always 0
1245
int codesetLen = reader.readByte();
1246            int command = reader.readByte();
1247            if (command != COMMAND_TESTCONNECTION)
1248            {
1249                try {
1250                    checkAddressIsLocal(session.clientSocket.getInetAddress());
1251                }catch (Exception JavaDoc e)
1252                {
1253                    notLocalMessage = e.getMessage();
1254                }
1255            }
1256            if (notLocalMessage != null)
1257            {
1258                sendMessage(writer, ERROR,notLocalMessage);
1259                session.langUtil = null;
1260                currentSession = null;
1261                return;
1262            }
1263
1264            switch(command)
1265            {
1266                case COMMAND_SHUTDOWN:
1267                    sendOK(writer);
1268                    directShutdown();
1269                    break;
1270                case COMMAND_TRACE:
1271                    sessionArg = reader.readNetworkInt();
1272                    boolean on = (reader.readByte() == 1);
1273                    if (setTrace(on))
1274                    {
1275                        sendOK(writer);
1276                    }
1277                    else
1278                    {
1279                        sendMessage(writer, ERROR,
1280                            localizeMessage("DRDA_SessionNotFound.U",
1281                            (session.langUtil == null) ? langUtil : session.langUtil,
1282                            new String JavaDoc [] {new Integer JavaDoc(sessionArg).toString()}));
1283                    }
1284                    break;
1285                case COMMAND_TRACEDIRECTORY:
1286                    setTraceDirectory(reader.readCmdString());
1287                    sendOK(writer);
1288                    consolePropertyMessage("DRDA_TraceDirectoryChange.I", traceDirectory);
1289                    break;
1290                case COMMAND_TESTCONNECTION:
1291                    databaseArg = reader.readCmdString();
1292                    userArg = reader.readCmdString();
1293                    passwordArg = reader.readCmdString();
1294                    if (databaseArg != null)
1295                        connectToDatabase(writer, databaseArg, userArg, passwordArg);
1296                    else
1297                        sendOK(writer);
1298                    break;
1299                case COMMAND_LOGCONNECTIONS:
1300                    boolean log = (reader.readByte() == 1);
1301                    setLogConnections(log);
1302                    sendOK(writer);
1303                    consolePropertyMessage("DRDA_LogConnectionsChange.I",
1304                        (log ? "DRDA_ON.I" : "DRDA_OFF.I"));
1305                    break;
1306                case COMMAND_SYSINFO:
1307                    sendSysInfo(writer);
1308                    break;
1309                case COMMAND_PROPERTIES:
1310                    sendPropInfo(writer);
1311                    break;
1312                case COMMAND_RUNTIME_INFO:
1313                    sendRuntimeInfo(writer);
1314                    break;
1315                case COMMAND_MAXTHREADS:
1316                    int max = reader.readNetworkInt();
1317                    try {
1318                        setMaxThreads(max);
1319                    }catch (Exception JavaDoc e) {
1320                        sendMessage(writer, ERROR, e.getMessage());
1321                        return;
1322                    }
1323                    int newval = getMaxThreads();
1324                    sendOKInt(writer, newval);
1325                    consolePropertyMessage("DRDA_MaxThreadsChange.I",
1326                        new Integer JavaDoc(newval).toString());
1327                    break;
1328                case COMMAND_TIMESLICE:
1329                    int timeslice = reader.readNetworkInt();
1330                    try {
1331                        setTimeSlice(timeslice);
1332                    }catch (Exception JavaDoc e) {
1333                        sendMessage(writer, ERROR, e.getMessage());
1334                        return;
1335                    }
1336                    newval = getTimeSlice();
1337                    sendOKInt(writer, newval);
1338                    consolePropertyMessage("DRDA_TimeSliceChange.I",
1339                        new Integer JavaDoc(newval).toString());
1340                    break;
1341            }
1342        } catch (DRDAProtocolException e) {
1343            //we need to handle this since we aren't in DRDA land here
1344
consoleExceptionPrintTrace(e);
1345
1346        } catch (Exception JavaDoc e) {
1347            consoleExceptionPrintTrace(e);
1348        }
1349        finally {
1350            session.langUtil = null;
1351            currentSession = null;
1352        }
1353    }
1354    /**
1355     * Get the next session for the thread to work on
1356     * Called from DRDAConnThread after session completes or timeslice
1357     * exceeded.
1358     *
1359     * If there is a waiting session, pick it up and put currentSession
1360     * at the back of the queue if there is one.
1361     * @param currentSession session thread is currently working on
1362     *
1363     * @return next session to work on, could be same as current session
1364     */

1365    protected Session getNextSession(Session currentSession)
1366    {
1367        Session retval = null;
1368        if (shutdown == true)
1369            return retval;
1370        synchronized (runQueue)
1371        {
1372            try {
1373                // nobody waiting - go on with current session
1374
if (runQueue.size() == 0)
1375                {
1376                    // no current session - wait for some work
1377
if (currentSession == null)
1378                    {
1379                        while (runQueue.size() == 0)
1380                        {
1381                            // This thread has nothing to do now so
1382
// we will add it to freeThreads
1383
freeThreads++;
1384                            runQueue.wait();
1385                            if (shutdown == true)
1386                                return null;
1387                            freeThreads--;
1388                        }
1389                    }
1390                    else
1391                        return currentSession;
1392                }
1393                retval = (Session) runQueue.elementAt(0);
1394                runQueue.removeElementAt(0);
1395                if (currentSession != null)
1396                    runQueueAdd(currentSession);
1397            } catch (InterruptedException JavaDoc e) {
1398            // If for whatever reason (ex. database shutdown) a waiting thread is
1399
// interrupted while in this method, that thread is going to be
1400
// closed down, so we need to decrement the number of threads
1401
// that will be available for use.
1402
freeThreads--;
1403            }
1404        }
1405        return retval;
1406    }
1407    /**
1408     * Get the stored application requester or store if we haven't seen it yet
1409     *
1410     * @param appRequester Application Requester to look for
1411     *
1412     * @return stored application requester
1413     */

1414    protected AppRequester getAppRequester(AppRequester appRequester)
1415    {
1416        AppRequester s = null;
1417
1418        if (SanityManager.DEBUG) {
1419            if (appRequester == null)
1420                SanityManager.THROWASSERT("null appRequester in getAppRequester");
1421        }
1422
1423        if (!appRequesterTable.isEmpty())
1424            s = (AppRequester)appRequesterTable.get(appRequester.prdid);
1425
1426        if (s == null)
1427        {
1428            appRequesterTable.put(appRequester.prdid, appRequester);
1429            return appRequester;
1430        }
1431        else
1432        {
1433            //compare just in case there are some differences
1434
//if they are different use the one we just read in
1435
if (s.equals(appRequester))
1436                return s;
1437            else
1438                return appRequester;
1439        }
1440    }
1441    /**
1442     * Get the server manager level for a given manager
1443     *
1444     * @param manager codepoint for manager
1445     * @return manager level
1446     */

1447    protected int getManagerLevel(int manager)
1448    {
1449        int mindex = CodePoint.getManagerIndex(manager);
1450        if (SanityManager.DEBUG) {
1451            if (mindex == CodePoint.UNKNOWN_MANAGER)
1452            SanityManager.THROWASSERT("manager out of bounds");
1453        }
1454        return MGR_LEVELS[mindex];
1455    }
1456    /**
1457     * Check whether a CCSID code page is supported
1458     *
1459     * @param ccsid CCSID to check
1460     * @return true if supported; false otherwise
1461     */

1462    protected boolean supportsCCSID(int ccsid)
1463    {
1464        try {
1465            CharacterEncodings.getJavaEncoding(ccsid);
1466            }
1467        catch (Exception JavaDoc e) {
1468            return false;
1469        }
1470        return true;
1471    }
1472    /**
1473     * Put property message on console
1474     *
1475     * @param msgProp message property key
1476     *
1477     * @throws Exception if an error occurs
1478     */

1479    protected void consolePropertyMessage(String JavaDoc msgProp)
1480        throws Exception JavaDoc
1481    {
1482        consolePropertyMessageWork(msgProp, null);
1483    }
1484    /**
1485     * Put property message on console
1486     *
1487     * @param msgProp message property key
1488     * @param arg argument for message
1489     *
1490     * @throws Exception if an error occurs
1491     */

1492    protected void consolePropertyMessage(String JavaDoc msgProp, String JavaDoc arg)
1493        throws Exception JavaDoc
1494    {
1495        consolePropertyMessageWork(msgProp, new String JavaDoc [] {arg});
1496    }
1497    /**
1498     * Put property message on console
1499     *
1500     * @param msgProp message property key
1501     * @param args argument array for message
1502     *
1503     * @throws Exception if an error occurs
1504     */

1505    protected void consolePropertyMessage(String JavaDoc msgProp, String JavaDoc [] args)
1506        throws Exception JavaDoc
1507    {
1508        consolePropertyMessageWork(msgProp, args);
1509    }
1510    /**
1511     * Is this the command protocol
1512     *
1513     * @param val
1514     */

1515    protected static boolean isCmd(String JavaDoc val)
1516    {
1517        if (val.equals(COMMAND_HEADER))
1518            return true;
1519        else
1520            return false;
1521    }
1522
1523    /*******************************************************************************/
1524    /* Private methods */
1525    /*******************************************************************************/
1526    /**
1527     * Write Command reply
1528     *
1529     * @param writer writer to use
1530     *
1531     * @throws Exception if a problem occurs sending OK
1532     */

1533    private void writeCommandReplyHeader(DDMWriter writer) throws Exception JavaDoc
1534    {
1535        writer.setCMDProtocol();
1536        writer.writeString(REPLY_HEADER);
1537    }
1538     
1539    /**
1540     * Send OK from server to client after processing a command
1541     *
1542     * @param writer writer to use for sending OK
1543     *
1544     * @throws Exception if a problem occurs sending OK
1545     */

1546    private void sendOK(DDMWriter writer) throws Exception JavaDoc
1547    {
1548        writeCommandReplyHeader(writer);
1549        writer.writeByte(OK);
1550        writer.flush();
1551    }
1552    /**
1553     * Send OK and int value
1554     *
1555     * @param writer writer to use for sending
1556     * @param val int val to send
1557     *
1558     * @throws Exception if a problem occurs
1559     */

1560    private void sendOKInt(DDMWriter writer, int val) throws Exception JavaDoc
1561    {
1562        writeCommandReplyHeader(writer);
1563        writer.writeByte(OK);
1564        writer.writeNetworkInt(val);
1565        writer.flush();
1566    }
1567    /**
1568     * Send Error or Warning from server to client after processing a command
1569     *
1570     * @param writer writer to use for sending message
1571     * @param messageType 1 for Warning, 2 for Error 3 for SQLError
1572     * @param message message
1573     *
1574     * @throws Exception if a problem occurs sending message
1575     */

1576    private void sendMessage(DDMWriter writer, int messageType, String JavaDoc message)
1577        throws Exception JavaDoc
1578    {
1579        writeCommandReplyHeader(writer);
1580        writer.writeByte(messageType);
1581        writer.writeLDString(message);
1582        writer.flush();
1583    }
1584    /**
1585     * Send SQL Exception from server to client after processing a command
1586     *
1587     * @param writer writer to use for sending message
1588     * @param se Cloudscape exception
1589     * @param type type of exception, SQLERROR or SQLWARNING
1590     *
1591     * @throws Exception if a problem occurs sending message
1592     */

1593    private void sendSQLMessage(DDMWriter writer, SQLException JavaDoc se, int type)
1594        throws Exception JavaDoc
1595    {
1596        StringBuffer JavaDoc locMsg = new StringBuffer JavaDoc();
1597        //localize message if necessary
1598
while (se != null)
1599        {
1600            if (currentSession != null && currentSession.langUtil != null &&
1601                se instanceof EmbedSQLException)
1602            {
1603                locMsg.append(se.getSQLState()+":"+
1604                    MessageService.getLocalizedMessage(
1605                    currentSession.langUtil.getLocale(), ((EmbedSQLException)se).getMessageId(),
1606                    ((EmbedSQLException)se).getArguments()));
1607            }
1608            else
1609                locMsg.append(se.getSQLState()+":"+se.getMessage());
1610            se = se.getNextException();
1611            if (se != null)
1612                locMsg.append("\n");
1613        }
1614        sendMessage(writer, type, locMsg.toString());
1615    }
1616    /**
1617     * Send SysInfo information from server to client
1618     *
1619     * @param writer writer to use for sending sysinfo
1620     *
1621     * @throws Exception if a problem occurs sending value
1622     */

1623    private void sendSysInfo(DDMWriter writer) throws Exception JavaDoc
1624    {
1625        StringBuffer JavaDoc sysinfo = new StringBuffer JavaDoc();
1626        sysinfo.append(getNetSysInfo());
1627        sysinfo.append(getCLSSysInfo());
1628        try {
1629            writeCommandReplyHeader(writer);
1630            writer.writeByte(0); //O.K.
1631
writer.writeLDString(sysinfo.toString());
1632        } catch (DRDAProtocolException e) {
1633            consolePropertyMessage("DRDA_SysInfoWriteError.S", e.getMessage());
1634        }
1635        writer.flush();
1636    }
1637    
1638    /**
1639     * Send RuntimeInfo information from server to client
1640     *
1641     * @param writer writer to use for sending sysinfo
1642     *
1643     * @throws Exception if a problem occurs sending value
1644     */

1645    private void sendRuntimeInfo(DDMWriter writer) throws Exception JavaDoc
1646    {
1647        try {
1648            writeCommandReplyHeader(writer);
1649            writer.writeByte(0); //O.K.
1650
writer.writeLDString(getRuntimeInfo());
1651                } catch (DRDAProtocolException e) {
1652            consolePropertyMessage("DRDA_SysInfoWriteError.S", e.getMessage());
1653        }
1654        writer.flush();
1655    }
1656
1657    
1658
1659    /**
1660     * Send property information from server to client
1661     *
1662     * @param writer writer to use for sending sysinfo
1663     *
1664     * @throws Exception if a problem occurs sending value
1665     */

1666    private void sendPropInfo(DDMWriter writer) throws Exception JavaDoc
1667    {
1668        try {
1669            ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc();
1670            Properties JavaDoc p = getPropertyValues();
1671            p.store(out, "NetworkServerControl properties");
1672            try {
1673                writeCommandReplyHeader(writer);
1674                writer.writeByte(0); //O.K.
1675
writer.writeLDBytes(out.toByteArray());
1676            } catch (DRDAProtocolException e) {
1677                consolePropertyMessage("DRDA_PropInfoWriteError.S", e.getMessage());
1678            }
1679            writer.flush();
1680        }
1681        catch (Exception JavaDoc e) {
1682            consoleExceptionPrintTrace(e);
1683        }
1684    }
1685
1686    /**
1687     * Get Net Server information
1688     *
1689     * @return system information for the Network Server
1690     */

1691    private String JavaDoc getNetSysInfo()
1692    {
1693        StringBuffer JavaDoc sysinfo = new StringBuffer JavaDoc();
1694        LocalizedResource localLangUtil = langUtil;
1695        if (currentSession != null && currentSession.langUtil != null)
1696        localLangUtil = currentSession.langUtil;
1697        sysinfo.append(localLangUtil.getTextMessage("DRDA_SysInfoBanner.I")+ "\n");
1698        sysinfo.append(localLangUtil.getTextMessage("DRDA_SysInfoVersion.I")+ " " + att_srvrlslv);
1699        sysinfo.append(" ");
1700        sysinfo.append(localLangUtil.getTextMessage("DRDA_SysInfoBuild.I")+ " " + buildNumber);
1701        sysinfo.append(" ");
1702        sysinfo.append(localLangUtil.getTextMessage("DRDA_SysInfoDrdaPRDID.I")+ " " + prdId);
1703        if (SanityManager.DEBUG)
1704        {
1705            sysinfo.append(" ** SANE BUILD **");
1706        }
1707        sysinfo.append("\n");
1708        // add property information
1709
Properties JavaDoc p = getPropertyValues();
1710        ByteArrayOutputStream JavaDoc bos = new ByteArrayOutputStream JavaDoc();
1711        PrintStream JavaDoc ps = new PrintStream JavaDoc(bos);
1712        p.list(ps);
1713        sysinfo.append(bos.toString());
1714        return sysinfo.toString();
1715    }
1716
1717    /**
1718     * @see NetworkServerControl#getRuntimeInfo
1719     */

1720    private String JavaDoc getRuntimeInfo()
1721    {
1722        return buildRuntimeInfo(langUtil);
1723    }
1724
1725    /**
1726     * Get Cloudscape information
1727     *
1728     * @return system information for Cloudscape
1729     *
1730     * @throws IOException if a problem occurs encoding string
1731     */

1732    private String JavaDoc getCLSSysInfo() throws IOException JavaDoc
1733    {
1734        ByteArrayOutputStream JavaDoc bos = new ByteArrayOutputStream JavaDoc();
1735        LocalizedResource localLangUtil = langUtil;
1736        if (currentSession != null && currentSession.langUtil != null)
1737        localLangUtil = currentSession.langUtil;
1738        LocalizedOutput aw = localLangUtil.getNewOutput(bos);
1739        org.apache.derby.impl.tools.sysinfo.Main.getMainInfo(aw, false);
1740        return bos.toString();
1741    }
1742
1743
1744    /**
1745     * Execute the command given on the command line
1746     *
1747     * @param args array of arguments indicating command to be executed
1748     *
1749     * @exception Exception throws an exception if an error occurs
1750     * see class comments for more information
1751     */

1752    public void executeWork(String JavaDoc args[]) throws Exception JavaDoc
1753    {
1754        // For convenience just use NetworkServerControlImpls log writer for user messages
1755
logWriter = makePrintWriter(System.out);
1756        
1757        int command = 0;
1758        if (args.length > 0)
1759            command = findCommand(args);
1760        else
1761        {
1762            consolePropertyMessage("DRDA_NoArgs.U");
1763        }
1764
1765        // if we didn't have a valid command just return - error already generated
1766
if (command == COMMAND_UNKNOWN)
1767            return;
1768
1769        // check that we have the right number of required arguments
1770
if (commandArgs.size() != COMMAND_ARGS[command])
1771            consolePropertyMessage("DRDA_InvalidNoArgs.U", COMMANDS[command]);
1772        int min;
1773        int max;
1774
1775
1776        switch (command)
1777        {
1778            case COMMAND_START:
1779                // the server was started from the command line, shutdown the
1780
// databases when the server is shutdown
1781
shutdownDatabasesOnShutdown = true;
1782                blockingStart(makePrintWriter(System.out));
1783                break;
1784            case COMMAND_SHUTDOWN:
1785                shutdown();
1786                consolePropertyMessage("DRDA_ShutdownSuccess.I", new String JavaDoc []
1787                                {att_srvclsnm, versionString,
1788                                getFormattedTimestamp()});
1789                break;
1790            case COMMAND_TRACE:
1791                {
1792                    boolean on = isOn((String JavaDoc)commandArgs.elementAt(0));
1793                    trace(sessionArg, on);
1794                    consoleTraceMessage(sessionArg, on);
1795                    break;
1796                }
1797            case COMMAND_TRACEDIRECTORY:
1798                setTraceDirectory((String JavaDoc) commandArgs.elementAt(0));
1799                consolePropertyMessage("DRDA_TraceDirectoryChange.I", traceDirectory);
1800                break;
1801            case COMMAND_TESTCONNECTION:
1802                ping();
1803                consolePropertyMessage("DRDA_ConnectionTested.I", new String JavaDoc []
1804                    {hostArg, (new Integer JavaDoc(portNumber)).toString()});
1805                break;
1806            case COMMAND_LOGCONNECTIONS:
1807                {
1808                    boolean on = isOn((String JavaDoc)commandArgs.elementAt(0));
1809                    logConnections(on);
1810                    consolePropertyMessage("DRDA_LogConnectionsChange.I", on ? "DRDA_ON.I" : "DRDA_OFF.I");
1811                    break;
1812                }
1813            case COMMAND_SYSINFO:
1814                {
1815                    String JavaDoc info = sysinfo();
1816                    consoleMessage(info);
1817                    break;
1818                }
1819            case COMMAND_MAXTHREADS:
1820                max = 0;
1821                try{
1822                    max = Integer.parseInt((String JavaDoc)commandArgs.elementAt(0));
1823                }catch(NumberFormatException JavaDoc e){
1824                    consolePropertyMessage("DRDA_InvalidValue.U", new String JavaDoc []
1825                        {(String JavaDoc)commandArgs.elementAt(0), "maxthreads"});
1826                }
1827                if (max < MIN_MAXTHREADS)
1828                    consolePropertyMessage("DRDA_InvalidValue.U", new String JavaDoc []
1829                        {new Integer JavaDoc(max).toString(), "maxthreads"});
1830                netSetMaxThreads(max);
1831
1832                break;
1833            case COMMAND_RUNTIME_INFO:
1834                String JavaDoc reply = runtimeInfo();
1835                consoleMessage(reply);
1836                break;
1837            case COMMAND_TIMESLICE:
1838                int timeslice = 0;
1839                String JavaDoc timeSliceArg = (String JavaDoc)commandArgs.elementAt(0);
1840                try{
1841                    timeslice = Integer.parseInt(timeSliceArg);
1842                }catch(NumberFormatException JavaDoc e){
1843                    consolePropertyMessage("DRDA_InvalidValue.U", new String JavaDoc []
1844                        {(String JavaDoc)commandArgs.elementAt(0), "timeslice"});
1845                }
1846                if (timeslice < MIN_TIMESLICE)
1847                    consolePropertyMessage("DRDA_InvalidValue.U", new String JavaDoc []
1848                        {new Integer JavaDoc(timeslice).toString(), "timeslice"});
1849                netSetTimeSlice(timeslice);
1850                
1851                break;
1852            default:
1853                //shouldn't get here
1854
if (SanityManager.DEBUG)
1855                    SanityManager.THROWASSERT("Invalid command in switch:"+ command);
1856        }
1857    }
1858
1859  
1860    /**
1861     * Add session to the run queue
1862     *
1863     * @param clientSession session needing work
1864     */

1865    private void runQueueAdd(Session clientSession)
1866    {
1867        synchronized(runQueue)
1868        {
1869            runQueue.addElement(clientSession);
1870            runQueue.notify();
1871        }
1872    }
1873    /**
1874     * Go through the arguments and find the command and save the dash arguments
1875     * and arguments to the command. Only one command is allowed in the argument
1876     * list.
1877     *
1878     * @param args arguments to search
1879     *
1880     * @return command
1881     */

1882    private int findCommand(String JavaDoc [] args) throws Exception JavaDoc
1883    {
1884        try {
1885            // process the dashArgs and pull out the command args
1886
int i = 0;
1887            int newpos = 0;
1888            while (i < args.length)
1889            {
1890                if (args[i].startsWith("-"))
1891                {
1892                    newpos = processDashArg(i, args);
1893                    if (newpos == i)
1894                        commandArgs.addElement(args[i++]);
1895                    else
1896                        i = newpos;
1897                }
1898                else
1899                    commandArgs.addElement(args[i++]);
1900            }
1901                    
1902            // look up command
1903
if (commandArgs.size() > 0)
1904            {
1905                for (i = 0; i < COMMANDS.length; i++)
1906                {
1907                    if (StringUtil.SQLEqualsIgnoreCase(COMMANDS[i],
1908                                                       (String JavaDoc)commandArgs.firstElement()))
1909                    {
1910                        commandArgs.removeElementAt(0);
1911                        return i;
1912                    }
1913                }
1914            }
1915            // didn't find command
1916
consolePropertyMessage("DRDA_UnknownCommand.U",
1917                (String JavaDoc) commandArgs.firstElement());
1918        } catch (Exception JavaDoc e) {
1919            if (e.getMessage().equals(NetworkServerControlImpl.UNEXPECTED_ERR))
1920                throw e;
1921            //Ignore expected exceptions, they will have been
1922
//handled by the consolePropertyMessage routine
1923
}
1924        return COMMAND_UNKNOWN;
1925    }
1926    /**
1927     * Get the dash argument. Optional arguments are formated as -x value.
1928     *
1929     * @param pos starting point
1930     * @param args arguments to search
1931     *
1932     * @return command
1933     *
1934     * @exception Exception thrown if an error occurs
1935     */

1936    private int processDashArg(int pos, String JavaDoc[] args)
1937        throws Exception JavaDoc
1938    {
1939        //check for a negative number
1940
char c = args[pos].charAt(1);
1941        if (c >= '0' && c <= '9')
1942            return pos;
1943        int dashArg = -1;
1944        for (int i = 0; i < DASHARGS.length; i++)
1945        {
1946            if (DASHARGS[i].equals(args[pos].substring(1)))
1947            {
1948                dashArg = i;
1949                pos++;
1950                break;
1951            }
1952        }
1953        if (dashArg == -1)
1954            consolePropertyMessage("DRDA_UnknownArgument.U", args[pos]);
1955        switch (dashArg)
1956        {
1957            case DASHARG_PORT:
1958                if (pos < args.length)
1959                {
1960                    try{
1961                        portNumber = Integer.parseInt(args[pos]);
1962                    }catch(NumberFormatException JavaDoc e){
1963                        consolePropertyMessage("DRDA_InvalidValue.U",
1964                            new String JavaDoc [] {args[pos], "DRDA_PortNumber.I"});
1965                    }
1966                }
1967                else
1968                    consolePropertyMessage("DRDA_MissingValue.U", "DRDA_PortNumber.I");
1969                break;
1970            case DASHARG_HOST:
1971                if (pos < args.length)
1972                {
1973                    hostArg = args[pos];
1974                }
1975                else
1976                    consolePropertyMessage("DRDA_MissingValue.U", "DRDA_Host.I");
1977                break;
1978            case DASHARG_DATABASE:
1979                if (pos < args.length)
1980                    databaseArg = args[pos];
1981                else
1982                    consolePropertyMessage("DRDA_MissingValue.U",
1983                        "DRDA_DatabaseDirectory.I");
1984                break;
1985            case DASHARG_USER:
1986                if (pos < args.length)
1987                {
1988                    userArg = args[pos++];
1989                    if (pos < args.length)
1990                        passwordArg = args[pos];
1991                    else
1992                        consolePropertyMessage("DRDA_MissingValue.U",
1993                            "DRDA_Password.I");
1994                }
1995                else
1996                    consolePropertyMessage("DRDA_MissingValue.U", "DRDA_User.I");
1997                break;
1998            case DASHARG_ENCALG:
1999                if (pos < args.length)
2000                    encAlgArg = args[pos];
2001                else
2002                    consolePropertyMessage("DRDA_MissingValue.U",
2003                        "DRDA_EncryptionAlgorithm.I");
2004                break;
2005            case DASHARG_ENCPRV:
2006                if (pos < args.length)
2007                    encPrvArg = args[pos];
2008                else
2009                    consolePropertyMessage("DRDA_MissingValue.U",
2010                        "DRDA_EncryptionProvider.I");
2011                break;
2012            case DASHARG_LOADSYSIBM:
2013                break;
2014            case DASHARG_SESSION:
2015                if (pos < args.length)
2016                    try{
2017                        sessionArg = Integer.parseInt(args[pos]);
2018                    }catch(NumberFormatException JavaDoc e){
2019                        consolePropertyMessage("DRDA_InvalidValue.U",
2020                            new String JavaDoc [] {args[pos], "DRDA_Session.I"});
2021                    }
2022                else
2023                    consolePropertyMessage("DRDA_MissingValue.U", "DRDA_Session.I");
2024                break;
2025            default:
2026                //shouldn't get here
2027
}
2028        return pos+1;
2029    }
2030
2031    /**
2032     * Is string "on" or "off"
2033     *
2034     * @param arg string to check
2035     *
2036     * @return true if string is "on", false if string is "off"
2037     *
2038     * @exception Exception thrown if string is not one of "on" or "off"
2039     */

2040    private boolean isOn(String JavaDoc arg)
2041        throws Exception JavaDoc
2042    {
2043        if (StringUtil.SQLEqualsIgnoreCase(arg, "on"))
2044            return true;
2045        else if (!StringUtil.SQLEqualsIgnoreCase(arg, "off"))
2046            consolePropertyMessage("DRDA_OnOffValue.U", arg);
2047        return false;
2048    }
2049
2050    /**
2051     * Set up client socket to send a command to the network server
2052     *
2053     * @exception Exception thrown if exception encountered
2054     */

2055    private void setUpSocket() throws Exception JavaDoc
2056    {
2057        
2058        try {
2059            clientSocket = (Socket JavaDoc) AccessController.doPrivileged(
2060                                new PrivilegedExceptionAction JavaDoc() {
2061                                        
2062                                    public Object JavaDoc run() throws UnknownHostException JavaDoc,IOException JavaDoc
2063                                    {
2064                                        if (hostAddress == null)
2065                                            hostAddress = InetAddress.getByName(hostArg);
2066
2067                                        // JDK131 can't connect with a client
2068
// socket with 0.0.0.0 (all addresses) so we will
2069
// getLocalHost() which will suffice.
2070
InetAddress JavaDoc connectAddress;
2071                                        if (JVMInfo.JDK_ID <= JVMInfo.J2SE_13 &&
2072                                            hostAddress.getHostAddress().equals("0.0.0.0"))
2073                                            connectAddress = InetAddress.getLocalHost();
2074                                        else
2075                                            connectAddress = hostAddress;
2076
2077                                        return new Socket JavaDoc(connectAddress, portNumber);
2078                                    }
2079                                }
2080                            );
2081        } catch (PrivilegedActionException JavaDoc pae) {
2082            Exception JavaDoc e1 = pae.getException();
2083            if (e1 instanceof UnknownHostException JavaDoc) {
2084                    consolePropertyMessage("DRDA_UnknownHost.S", hostArg);
2085            }
2086            else if (e1 instanceof IOException JavaDoc) {
2087                    consolePropertyMessage("DRDA_NoIO.S",
2088                        new String JavaDoc [] {hostArg, (new Integer JavaDoc(portNumber)).toString()});
2089            }
2090        } catch (Exception JavaDoc e) {
2091        // If we find other (unexpected) errors, we ultimately exit--so make
2092
// sure we print the error message before doing so (Beetle 5033).
2093
throwUnexpectedException(e);
2094        }
2095
2096        try
2097        {
2098           clientIs = clientSocket.getInputStream();
2099           clientOs = clientSocket.getOutputStream();
2100        } catch (IOException JavaDoc e) {
2101            consolePropertyMessage("DRDA_NoInputStream.I");
2102            throw e;
2103        }
2104    }
2105
2106    
2107    private void checkAddressIsLocal(InetAddress JavaDoc inetAddr) throws UnknownHostException JavaDoc,Exception JavaDoc
2108    {
2109        for(int i = 0; i < localAddresses.size(); i++)
2110        {
2111            if (inetAddr.equals((InetAddress JavaDoc)localAddresses.get(i)))
2112            {
2113                return;
2114            }
2115        }
2116        consolePropertyMessage("DRDA_NeedLocalHost.S", new String JavaDoc[] {inetAddr.getHostName(),serverSocket.getInetAddress().getHostName()});
2117
2118    }
2119
2120
2121    /**
2122     * Build local address list to allow admin commands.
2123     *
2124     * @param bindAddr Address on which server was started
2125     *
2126     * Note: Some systems may not support localhost.
2127     * In that case a console message will print for the localhost entries,
2128     * but the server will continue to start.
2129     **/

2130    private void buildLocalAddressList(InetAddress JavaDoc bindAddr)
2131    {
2132            localAddresses = new ArrayList JavaDoc(3);
2133            localAddresses.add(bindAddr);
2134            try {
2135                localAddresses.add(InetAddress.getLocalHost());
2136                localAddresses.add(InetAddress.getByName("localhost"));
2137            }catch(UnknownHostException JavaDoc uhe)
2138            {
2139                try {
2140                    consolePropertyMessage("DRDA_UnknownHostWarning.I",uhe.getMessage());
2141                } catch (Exception JavaDoc e)
2142                { // just a warning shouldn't actually throw an exception
2143
}
2144            }
2145    }
2146    
2147    /**
2148     * Routines for writing commands for NetworkServerControlImpl being used as a client
2149     * to a server
2150     */

2151
2152    /**
2153     * Write command header consisting of command header string and protocol
2154     * version and command
2155     *
2156     * @param command command to be written
2157     *
2158     * @exception Exception throws an exception if an error occurs
2159     */

2160    private void writeCommandHeader(int command) throws Exception JavaDoc
2161    {
2162        try {
2163            writeString(COMMAND_HEADER);
2164            commandOs.writeByte((byte)((PROTOCOL_VERSION & 0xf0) >> 8 ));
2165            commandOs.writeByte((byte)(PROTOCOL_VERSION & 0x0f));
2166
2167            if (clientLocale != null && clientLocale != DEFAULT_LOCALE)
2168            {
2169                commandOs.writeByte(clientLocale.length());
2170                commandOs.writeBytes(clientLocale);
2171            }
2172            else
2173                commandOs.writeByte((byte) 0);
2174            commandOs.writeByte((byte) 0);
2175            commandOs.writeByte((byte) command);
2176        }
2177        catch (IOException JavaDoc e)
2178        {
2179            clientSocketError(e);
2180        }
2181    }
2182    /**
2183     * Write length delimited string string
2184     *
2185     * @param msg string to be written
2186     *
2187     * @exception Exception throws an exception if an error occurs
2188     */

2189    private void writeLDString(String JavaDoc msg) throws Exception JavaDoc
2190    {
2191        try {
2192            if (msg == null)
2193            {
2194                commandOs.writeShort(0);
2195            }
2196            else
2197            {
2198                commandOs.writeShort(msg.length());
2199                writeString(msg);
2200            }
2201        }
2202        catch (IOException JavaDoc e)
2203        {
2204            clientSocketError(e);
2205        }
2206    }
2207
2208    /** Write string
2209     *
2210     * @param msg String to write
2211     */

2212
2213    protected void writeString(String JavaDoc msg) throws Exception JavaDoc
2214    {
2215        byte[] msgBytes = msg.getBytes(DEFAULT_ENCODING);
2216        commandOs.write(msgBytes,0,msgBytes.length);
2217    }
2218
2219    /**
2220     * Write short
2221     *
2222     * @param value value to be written
2223     *
2224     * @exception Exception throws an exception if an error occurs
2225     */

2226    private void writeShort(int value) throws Exception JavaDoc
2227    {
2228        try {
2229            commandOs.writeByte((byte)((value & 0xf0) >> 8 ));
2230            commandOs.writeByte((byte)(value & 0x0f));
2231        }
2232        catch (IOException JavaDoc e)
2233        {
2234            clientSocketError(e);
2235        }
2236    }
2237    /**
2238     * Write byte
2239     *
2240     * @param value value to be written
2241     *
2242     * @exception Exception throws an exception if an error occurs
2243     */

2244    private void writeByte(int value) throws Exception JavaDoc
2245    {
2246        try {
2247            commandOs.writeByte((byte)(value & 0x0f));
2248        }
2249        catch (IOException JavaDoc e)
2250        {
2251            clientSocketError(e);
2252        }
2253    }
2254    /**
2255     * Send client message to server
2256     *
2257     *
2258     * @exception Exception throws an exception if an error occurs
2259     */

2260    private void send() throws Exception JavaDoc
2261    {
2262        try {
2263            byteArrayOs.writeTo(clientOs);
2264            commandOs.flush();
2265            byteArrayOs.reset(); //discard anything currently in the byte array
2266
}
2267        catch (IOException JavaDoc e)
2268        {
2269            clientSocketError(e);
2270        }
2271    }
2272    /**
2273     * Stream error writing to client socket
2274     */

2275    private void clientSocketError(IOException JavaDoc e) throws IOException JavaDoc
2276    {
2277        try {
2278            consolePropertyMessage("DRDA_ClientSocketError.S", e.getMessage());
2279        } catch (Exception JavaDoc ce) {} // catch the exception consolePropertyMessage will
2280
// throw since we also want to print a stack trace
2281
consoleExceptionPrintTrace(e);
2282            throw e;
2283    }
2284    /**
2285     * Read result from sending client message to server
2286     *
2287     * @exception Exception throws an exception if an error occurs
2288     */

2289    private void readResult() throws Exception JavaDoc
2290    {
2291        fillReplyBuffer();
2292        readCommandReplyHeader();
2293        if (replyBufferPos >= replyBufferCount)
2294            consolePropertyMessage("DRDA_InvalidReplyTooShort.S");
2295        int messageType = replyBuffer[replyBufferPos++] & 0xFF;
2296        if (messageType == OK) // O.K.
2297
return;
2298        // get error and display and throw exception
2299
String JavaDoc message = readLDString();
2300        if (messageType == SQLERROR)
2301            wrapSQLError(message);
2302        else if (messageType == SQLWARNING)
2303            wrapSQLWarning(message);
2304        else
2305            consolePropertyMessage(message);
2306    }
2307
2308    
2309
2310    /**
2311     * Ensure the reply buffer is at large enought to hold all the data;
2312     * don't just rely on OS level defaults
2313     *
2314     *
2315     * @param minimumBytesNeeded size of buffer required
2316     * @exception Exception throws an exception if a problem reading the reply
2317     */

2318    private void ensureDataInBuffer(int minimumBytesNeeded) throws Exception JavaDoc
2319    {
2320        // make sure the buffer is large enough
2321
while ((replyBufferCount - replyBufferPos) < minimumBytesNeeded)
2322        {
2323            try {
2324                int bytesRead = clientIs.read(replyBuffer, replyBufferCount, replyBuffer.length - replyBufferCount);
2325                replyBufferCount += bytesRead;
2326        
2327            } catch (IOException JavaDoc e)
2328            {
2329                clientSocketError(e);
2330            }
2331        }
2332    }
2333
2334
2335    /**
2336     * Fill the reply buffer with the reply allocates a reply buffer if one doesn't
2337     * exist
2338     *
2339     *
2340     * @exception Exception throws an exception if a problem reading the reply
2341     */

2342    private void fillReplyBuffer() throws Exception JavaDoc
2343    {
2344        if (replyBuffer == null)
2345            replyBuffer = new byte[MAXREPLY];
2346        try {
2347            replyBufferCount = clientIs.read(replyBuffer);
2348        }
2349        catch (IOException JavaDoc e)
2350        {
2351            clientSocketError(e);
2352        }
2353        if (replyBufferCount == -1)
2354            consolePropertyMessage("DRDA_InvalidReplyTooShort.S");
2355        replyBufferPos = 0;
2356    }
2357    /**
2358     * Read the command reply header from the server
2359     *
2360     * @exception Exception throws an exception if an error occurs
2361     */

2362    private void readCommandReplyHeader() throws Exception JavaDoc
2363    {
2364        ensureDataInBuffer(REPLY_HEADER_LENGTH);
2365        if (replyBufferCount < REPLY_HEADER_LENGTH)
2366        {
2367            consolePropertyMessage("DRDA_InvalidReplyHeader1.S", Integer.toString(replyBufferCount));
2368        }
2369        String JavaDoc header = new String JavaDoc(replyBuffer, 0, REPLY_HEADER_LENGTH, DEFAULT_ENCODING);
2370        if (!header.equals(REPLY_HEADER))
2371        {
2372            consolePropertyMessage("DRDA_InvalidReplyHeader2.S", header);
2373        }
2374        replyBufferPos += REPLY_HEADER_LENGTH;
2375    }
2376    /**
2377     * Read short from buffer
2378     * @exception Exception throws an exception if an error occurs
2379     */

2380    private int readShort() throws Exception JavaDoc
2381    {
2382        ensureDataInBuffer(2);
2383        if (replyBufferPos + 2 > replyBufferCount)
2384            consolePropertyMessage("DRDA_InvalidReplyTooShort.S");
2385        return ((replyBuffer[replyBufferPos++] & 0xff) << 8) +
2386                (replyBuffer[replyBufferPos++] & 0xff);
2387    }
2388    /**
2389     * Read int from buffer
2390     * @exception Exception throws an exception if an error occurs
2391     */

2392    private int readInt() throws Exception JavaDoc
2393    {
2394        ensureDataInBuffer(4);
2395        if (replyBufferPos + 4 > replyBufferCount)
2396            consolePropertyMessage("DRDA_InvalidReplyTooShort.S");
2397        return ((replyBuffer[replyBufferPos++] & 0xff) << 24) +
2398            ((replyBuffer[replyBufferPos++] & 0xff) << 16) +
2399            ((replyBuffer[replyBufferPos++] & 0xff) << 8) +
2400                (replyBuffer[replyBufferPos++] & 0xff);
2401    }
2402    /**
2403     * Read String reply
2404     *
2405     * @param msgKey error message key
2406     * @return string value or null
2407     * @exception Exception throws an error if problems reading reply
2408     */

2409    private String JavaDoc readStringReply(String JavaDoc msgKey) throws Exception JavaDoc
2410    {
2411        fillReplyBuffer();
2412        readCommandReplyHeader();
2413        if (replyBuffer[replyBufferPos++] == 0) // O.K.
2414
return readLDString();
2415        else
2416            consolePropertyMessage(msgKey);
2417        return null;
2418            
2419    }
2420
2421
2422
2423    
2424    /**
2425     * Read length delimited string from a buffer
2426     *
2427     * @return string value from buffer
2428     * @exception Exception throws an error if problems reading reply
2429     */

2430    private String JavaDoc readLDString() throws Exception JavaDoc
2431    {
2432        int strlen = readShort();
2433        ensureDataInBuffer(strlen);
2434        if (replyBufferPos + strlen > replyBufferCount)
2435            consolePropertyMessage("DRDA_InvalidReplyTooShort.S");
2436        String JavaDoc retval= new String JavaDoc(replyBuffer, replyBufferPos, strlen, DEFAULT_ENCODING);
2437        replyBufferPos += strlen;
2438        return retval;
2439    }
2440    /**
2441     * Read Bytes reply
2442     *
2443     * @param msgKey error message key
2444     * @return string value or null
2445     * @exception Exception throws an error if problems reading reply
2446     */

2447    private byte [] readBytesReply(String JavaDoc msgKey) throws Exception JavaDoc
2448    {
2449        fillReplyBuffer();
2450        readCommandReplyHeader();
2451        if (replyBuffer[replyBufferPos++] == 0) // O.K.
2452
return readLDBytes();
2453        else
2454            consolePropertyMessage(msgKey);
2455        return null;
2456            
2457    }
2458    /**
2459     * Read length delimited bytes from a buffer
2460     *
2461     * @return byte array from buffer
2462     * @exception Exception throws an error if problems reading reply
2463     */

2464    private byte[] readLDBytes() throws Exception JavaDoc
2465    {
2466        int len = readShort();
2467        ensureDataInBuffer(len);
2468        if (replyBufferPos + len > replyBufferCount)
2469            consolePropertyMessage("DRDA_InvalidReplyTooShort.S");
2470        byte [] retval = new byte[len];
2471        for (int i = 0; i < len; i++)
2472            retval[i] = replyBuffer[replyBufferPos++];
2473        return retval;
2474    }
2475
2476    /**
2477     * Initialize fields from system properties
2478     *
2479     */

2480    private void getPropertyInfo() throws Exception JavaDoc
2481    {
2482        //set values according to properties
2483

2484        String JavaDoc directory = PropertyUtil.getSystemProperty(Property.SYSTEM_HOME_PROPERTY);
2485        String JavaDoc propval = PropertyUtil.getSystemProperty(
2486            Property.DRDA_PROP_LOGCONNECTIONS);
2487        if (propval != null && StringUtil.SQLEqualsIgnoreCase(propval,"true"))
2488            setLogConnections(true);
2489        propval = PropertyUtil.getSystemProperty(Property.DRDA_PROP_TRACEALL);
2490        if (propval != null && StringUtil.SQLEqualsIgnoreCase(propval,
2491                                                              "true"))
2492            setTraceAll(true);
2493
2494        //If the derby.system.home property has been set, it is the default.
2495
//Otherwise, the default is the current directory.
2496
//If derby.system.home is not set, directory will be null and trace files will get
2497
//created in current directory.
2498
propval = PropertyUtil.getSystemProperty(Property.DRDA_PROP_TRACEDIRECTORY,directory);
2499        if(propval != null){
2500            if(propval.equals(""))
2501                propval = directory;
2502            setTraceDirectory(propval);
2503        }
2504
2505        //DERBY-375 If a system property is specified without any value, getProperty returns
2506
//an empty string. Use default values in such cases.
2507
propval = PropertyUtil.getSystemProperty(
2508            Property.DRDA_PROP_MINTHREADS);
2509        if (propval != null){
2510            if(propval.equals(""))
2511                propval = "0";
2512            setMinThreads(getIntPropVal(Property.DRDA_PROP_MINTHREADS, propval));
2513        }
2514
2515        propval = PropertyUtil.getSystemProperty(
2516            Property.DRDA_PROP_MAXTHREADS);
2517        if (propval != null){
2518            if(propval.equals(""))
2519                propval = "0";
2520            setMaxThreads(getIntPropVal(Property.DRDA_PROP_MAXTHREADS, propval));
2521        }
2522
2523
2524        propval = PropertyUtil.getSystemProperty(
2525            Property.DRDA_PROP_TIMESLICE);
2526        if (propval != null){
2527            if(propval.equals(""))
2528                propval = "0";
2529            setTimeSlice(getIntPropVal(Property.DRDA_PROP_TIMESLICE, propval));
2530        }
2531
2532        propval = PropertyUtil.getSystemProperty(
2533            Property.DRDA_PROP_PORTNUMBER);
2534        if (propval != null){
2535            if(propval.equals(""))
2536                propval = String.valueOf(NetworkServerControl.DEFAULT_PORTNUMBER);
2537            portNumber = getIntPropVal(Property.DRDA_PROP_PORTNUMBER, propval);
2538        }
2539
2540        propval = PropertyUtil.getSystemProperty(
2541            Property.DRDA_PROP_KEEPALIVE);
2542        if (propval != null &&
2543            StringUtil.SQLEqualsIgnoreCase(propval,"false"))
2544            keepAlive = false;
2545        
2546        propval = PropertyUtil.getSystemProperty(
2547            Property.DRDA_PROP_HOSTNAME);
2548        if (propval != null){
2549            if(propval.equals(""))
2550                hostArg = DEFAULT_HOST;
2551            else
2552                hostArg = propval;
2553        }
2554        propval = PropertyUtil.getSystemProperty(
2555                         NetworkServerControlImpl.DRDA_PROP_DEBUG);
2556        if (propval != null && StringUtil.SQLEqualsIgnoreCase(propval, "true"))
2557            debugOutput = true;
2558
2559        propval = PropertyUtil.getSystemProperty(
2560                Property.DRDA_PROP_SECURITYMECHANISM);
2561        if (propval != null){
2562            setSecurityMechanism(propval);
2563        }
2564
2565    }
2566
2567    /**
2568     * Retrieve the SECMEC integer value from the
2569     * user friendly security mechanism name
2570     * @param s security mechanism name
2571     * @return integer value , return the SECMEC value for
2572     * the security mechanism as defined by DRDA spec
2573     * or INVALID_OR_NOTSET_SECURITYMECHANISM if 's'
2574     * passed is invalid or not supported security
2575     * mechanism
2576     */

2577    private int getSecMecValue(String JavaDoc s)
2578    {
2579        int secmec = INVALID_OR_NOTSET_SECURITYMECHANISM;
2580
2581        if( StringUtil.SQLEqualsIgnoreCase(s,"USER_ONLY_SECURITY"))
2582                secmec = CodePoint.SECMEC_USRIDONL;
2583        else if( StringUtil.SQLEqualsIgnoreCase(s,"CLEAR_TEXT_PASSWORD_SECURITY"))
2584                secmec = CodePoint.SECMEC_USRIDPWD;
2585        else if( StringUtil.SQLEqualsIgnoreCase(s,"ENCRYPTED_USER_AND_PASSWORD_SECURITY"))
2586                secmec = CodePoint.SECMEC_EUSRIDPWD;
2587        else if( StringUtil.SQLEqualsIgnoreCase(s,"STRONG_PASSWORD_SUBSTITUTE_SECURITY"))
2588                secmec = CodePoint.SECMEC_USRSSBPWD;
2589        
2590        return secmec;
2591    }
2592
2593    /**
2594     * Retrieve the string name for the integer
2595     * secmec value
2596     * @param secmecVal secmec value
2597     * @return String - return the string name corresponding
2598     * to the secmec value if recognized else returns null
2599     */

2600    private String JavaDoc getStringValueForSecMec(int secmecVal)
2601    {
2602        switch(secmecVal)
2603        {
2604            case CodePoint.SECMEC_USRIDONL:
2605                return "USER_ONLY_SECURITY";
2606            
2607            case CodePoint.SECMEC_USRIDPWD:
2608                return "CLEAR_TEXT_PASSWORD_SECURITY";
2609            
2610            case CodePoint.SECMEC_EUSRIDPWD:
2611                return "ENCRYPTED_USER_AND_PASSWORD_SECURITY";
2612            
2613            case CodePoint.SECMEC_USRSSBPWD:
2614                return "STRONG_PASSWORD_SUBSTITUTE_SECURITY";
2615        }
2616        return null;
2617    }
2618   
2619    /**
2620     * This method returns whether EUSRIDPWD security mechanism
2621     * is supported or not. See class static block for more
2622     * info.
2623     * @return true if EUSRIDPWD is supported, false otherwise
2624     */

2625    boolean supportsEUSRIDPWD()
2626    {
2627        return SUPPORTS_EUSRIDPWD;
2628    }
2629    
2630    /**
2631     * Get integer property values
2632     *
2633     * @param propName property name
2634     * @param propVal string property value
2635     * @return integer value
2636     *
2637     * @exception Exception if not a valid integer
2638     */

2639    private int getIntPropVal(String JavaDoc propName, String JavaDoc propVal)
2640        throws Exception JavaDoc
2641    {
2642        int val = 0;
2643        try {
2644             val = (new Integer JavaDoc(propVal)).intValue();
2645        } catch (Exception JavaDoc e)
2646        {
2647            consolePropertyMessage("DRDA_InvalidPropVal.S", new String JavaDoc []
2648                {propName, propVal});
2649        }
2650        return val;
2651    }
2652
2653    /**
2654     * Handle console error message
2655     * - display on console and if it is a user error, display usage
2656     * - if user error or severe error, throw exception with message key and message
2657     *
2658     * @param messageKey message key
2659     * @param args arguments to message
2660     *
2661     * @throws Exception if an error occurs
2662     */

2663    private void consolePropertyMessageWork(String JavaDoc messageKey, String JavaDoc [] args)
2664        throws Exception JavaDoc
2665    {
2666        String JavaDoc locMsg = null;
2667
2668        int type = getMessageType(messageKey);
2669
2670        if (type == ERRTYPE_UNKNOWN)
2671            locMsg = messageKey;
2672        else
2673            locMsg = localizeMessage(messageKey, langUtil, args);
2674
2675        //display on the console
2676
consoleMessage(locMsg);
2677
2678        //if it is a user error display usage
2679
if (type == ERRTYPE_USER)
2680            usage();
2681
2682        //we may want to use a different locale for throwing the exception
2683
//since this can be sent to a browser with a different locale
2684
if (currentSession != null &&
2685                currentSession.langUtil != null &&
2686                type != ERRTYPE_UNKNOWN)
2687            locMsg = localizeMessage(messageKey, currentSession.langUtil, args);
2688
2689        // throw an exception for severe and user errors
2690
if (type == ERRTYPE_SEVERE || type == ERRTYPE_USER)
2691        {
2692            if (messageKey.equals("DRDA_SQLException.S"))
2693                throwSQLException(args[0]);
2694            else if (messageKey.equals("DRDA_SQLWarning.I"))
2695                throwSQLWarning(args[0]);
2696            else
2697                throw new Exception JavaDoc(messageKey+":"+locMsg);
2698        }
2699
2700        // throw an exception with just the message if the error type is
2701
// unknown
2702
if (type == ERRTYPE_UNKNOWN)
2703            throw new Exception JavaDoc(locMsg);
2704
2705        return;
2706
2707    }
2708    /**
2709     * Throw a SQL Exception which was sent over by a server
2710     * Format of the msg is SQLSTATE:localized message\nSQLSTATE:next localized message
2711     *
2712     * @param msg msg containing SQL Exception
2713     *
2714     * @throws SQLException
2715     */

2716    private void throwSQLException(String JavaDoc msg) throws SQLException JavaDoc
2717    {
2718        SQLException JavaDoc se = null;
2719        SQLException JavaDoc ne;
2720        SQLException JavaDoc ce = null;
2721        StringBuffer JavaDoc strbuf = new StringBuffer JavaDoc();
2722        StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(msg, "\n");
2723        String JavaDoc sqlstate = null;
2724        String JavaDoc str;
2725        while (tokenizer.hasMoreTokens())
2726        {
2727            str = tokenizer.nextToken();
2728            //start of the next message
2729
if (str.charAt(5) == ':')
2730            {
2731                if (strbuf.length() > 0)
2732                {
2733                    if (se == null)
2734                    {
2735                        se = new SQLException JavaDoc(strbuf.toString(), sqlstate);
2736                        ce = se;
2737                    }
2738                    else
2739                    {
2740                        ne = new SQLException JavaDoc(strbuf.toString(), sqlstate);
2741                        ce.setNextException(ne);
2742                        ce = ne;
2743                    }
2744                    strbuf = new StringBuffer JavaDoc();
2745                }
2746                strbuf.append(str.substring(6));
2747                sqlstate = str.substring(0,5);
2748            }
2749            else
2750                strbuf.append(str);
2751        }
2752        if (strbuf.length() > 0)
2753        {
2754            if (se == null)
2755            {
2756                se = new SQLException JavaDoc(strbuf.toString(), sqlstate);
2757                ce = se;
2758            }
2759            else
2760            {
2761                ne = new SQLException JavaDoc(strbuf.toString(), sqlstate);
2762                ce.setNextException(ne);
2763                ce = ne;
2764            }
2765        }
2766        throw se;
2767    }
2768    /**
2769     * Throw a SQL Warning which was sent over by a server
2770     * Format of the msg is SQLSTATE:localized message\nSQLSTATE:next localized message
2771     *
2772     * @param msg msg containing SQL Warning
2773     *
2774     * @throws SQLWarning
2775     */

2776    private void throwSQLWarning(String JavaDoc msg) throws SQLWarning JavaDoc
2777    {
2778        SQLWarning JavaDoc se = null;
2779        SQLWarning JavaDoc ne;
2780        SQLWarning JavaDoc ce = null;
2781        StringBuffer JavaDoc strbuf = new StringBuffer JavaDoc();
2782        StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(msg, "\n");
2783        String JavaDoc sqlstate = null;
2784        String JavaDoc str;
2785        while (tokenizer.hasMoreTokens())
2786        {
2787            str = tokenizer.nextToken();
2788            //start of the next message
2789
if (str.charAt(5) == ':')
2790            {
2791                if (strbuf.length() > 0)
2792                {
2793                    if (se == null)
2794                    {
2795                        se = new SQLWarning JavaDoc(strbuf.toString(), sqlstate);
2796                        ce = se;
2797                    }
2798                    else
2799                    {
2800                        ne = new SQLWarning JavaDoc(strbuf.toString(), sqlstate);
2801                        ce.setNextException(ne);
2802                        ce = ne;
2803                    }
2804                    strbuf = new StringBuffer JavaDoc();
2805                }
2806                strbuf.append(str.substring(6));
2807                sqlstate = str.substring(0,5);
2808            }
2809            else
2810                strbuf.append(str);
2811        }
2812        if (strbuf.length() > 0)
2813        {
2814            if (se == null)
2815            {
2816                se = new SQLWarning JavaDoc(strbuf.toString(), sqlstate);
2817                ce = se;
2818            }
2819            else
2820            {
2821                ne = new SQLWarning JavaDoc(strbuf.toString(), sqlstate);
2822                ce.setNextException(ne);
2823                ce = ne;
2824            }
2825        }
2826        throw se;
2827    }
2828
2829    /**
2830     * Print a trace for the (unexpected) exception received, then
2831     * throw a generic exception indicating that 1) an unexpected
2832     * exception was thrown, and 2) we've already printed the trace
2833     * (so don't do it again).
2834     *
2835     * @param e An unexpected exception.
2836     * @throws Exception with message UNEXPECTED_ERR.
2837     */

2838    private void throwUnexpectedException(Exception JavaDoc e)
2839     throws Exception JavaDoc {
2840
2841        consoleExceptionPrintTrace(e);
2842        throw new Exception JavaDoc(UNEXPECTED_ERR);
2843
2844    }
2845
2846    /**
2847     * Localize a message given a particular AppUI
2848     *
2849     * @param msgProp message key
2850     * @param localLangUtil LocalizedResource to use to localize message
2851     * @param args arguments to message
2852     *
2853     */

2854    private String JavaDoc localizeMessage(String JavaDoc msgProp, LocalizedResource localLangUtil, String JavaDoc [] args)
2855    {
2856        String JavaDoc locMsg = null;
2857        //check if the argument is a property
2858
if (args != null)
2859        {
2860            String JavaDoc [] argMsg = new String JavaDoc[args.length];
2861            for (int i = 0; i < args.length; i++)
2862            {
2863                if (isMsgProperty(args[i]))
2864                    argMsg[i] = localLangUtil.getTextMessage(args[i]);
2865                else
2866                    argMsg[i] = args[i];
2867            }
2868            switch (args.length)
2869            {
2870                case 1:
2871                    locMsg = localLangUtil.getTextMessage(msgProp, argMsg[0]);
2872                    break;
2873                case 2:
2874                    locMsg = localLangUtil.getTextMessage(msgProp, argMsg[0], argMsg[1]);
2875                    break;
2876                case 3:
2877                    locMsg = localLangUtil.getTextMessage(msgProp, argMsg[0], argMsg[1], argMsg[2]);
2878                    break;
2879                case 4:
2880                    locMsg = localLangUtil.getTextMessage(msgProp, argMsg[0], argMsg[1], argMsg[2], argMsg[3]);
2881                    break;
2882                default:
2883                    //shouldn't get here
2884
}
2885        }
2886        else
2887            locMsg = localLangUtil.getTextMessage(msgProp);
2888        return locMsg;
2889    }
2890    /**
2891     * Determine type of message
2892     *
2893     * @param msg message
2894     *
2895     * @return message type
2896     */

2897    private int getMessageType(String JavaDoc msg)
2898    {
2899        //all property messages should start with DRDA_
2900
if (!msg.startsWith(DRDA_MSG_PREFIX))
2901            return ERRTYPE_UNKNOWN;
2902        int startpos = msg.indexOf('.')+1;
2903        if (startpos >= msg.length())
2904            return ERRTYPE_UNKNOWN;
2905        if (msg.length() > (startpos + 1))
2906            return ERRTYPE_UNKNOWN;
2907        char type = msg.charAt(startpos);
2908        if (type == 'S')
2909            return ERRTYPE_SEVERE;
2910        if (type == 'U')
2911            return ERRTYPE_USER;
2912        if (type == 'I')
2913            return ERRTYPE_INFO;
2914        return ERRTYPE_UNKNOWN;
2915    }
2916    /**
2917     * Determine whether string is a property key or not
2918     * property keys start with DRDA_MSG_PREFIX
2919     *
2920     * @param msg message
2921     *
2922     * @return true if it is a property key; false otherwise
2923     */

2924    private boolean isMsgProperty(String JavaDoc msg)
2925    {
2926        if (msg.startsWith(DRDA_MSG_PREFIX))
2927            return true;
2928        else
2929            return false;
2930    }
2931    /**
2932     * Get the current value of logging connections
2933     *
2934     * @return true if logging connections is on; false otherwise
2935     */

2936    public boolean getLogConnections()
2937    {
2938        synchronized(logConnectionsSync) {
2939            return logConnections;
2940        }
2941    }
2942    /**
2943     * Set the current value of logging connections
2944     *
2945     * @param value true to turn logging connections on; false to turn it off
2946     */

2947    private void setLogConnections(boolean value)
2948    {
2949        synchronized(logConnectionsSync) {
2950            logConnections = value;
2951        }
2952        // update the value in all the threads
2953
synchronized(threadList) {
2954            for (Enumeration JavaDoc e = threadList.elements(); e.hasMoreElements(); )
2955            {
2956                DRDAConnThread thread = (DRDAConnThread)e.nextElement();
2957                thread.setLogConnections(value);
2958            }
2959        }
2960    }
2961
2962    /**
2963     * Set the security mechanism for derby.drda.securityMechanism
2964     * If this property is set, server will only allow connections
2965     * from client with this security mechanism.
2966     * This method will map the user friendly string representing
2967     * the security mechanism to the corresponding drda secmec value
2968     * @param s security mechanism string value
2969     * @throws Exception if value to set is invalid
2970     * @see Property#DRDA_PROP_SECURITYMECHANISM
2971     */

2972    private void setSecurityMechanism(String JavaDoc s)
2973        throws Exception JavaDoc
2974    {
2975       allowOnlySecurityMechanism = getSecMecValue(s);
2976       
2977       // if server vm cannot support EUSRIDPWD, then do not allow
2978
// derby.drda.securityMechanism to be set to EUSRIDPWD security
2979
// mechanism
2980
if ((allowOnlySecurityMechanism == INVALID_OR_NOTSET_SECURITYMECHANISM) ||
2981              (allowOnlySecurityMechanism == CodePoint.SECMEC_EUSRIDPWD &&
2982              !SUPPORTS_EUSRIDPWD))
2983           consolePropertyMessage("DRDA_InvalidValue.U", new String JavaDoc []
2984                       {s, Property.DRDA_PROP_SECURITYMECHANISM});
2985    }
2986    
2987    /**
2988     * get the security mechanism (secmec value) that the server
2989     * will accept connections from.
2990     * @return the securitymechanism value. It is value that
2991     * the derby.drda.securityMechanism was set to, if it is not set, then
2992     * it is equal to INVALID_OR_NOTSET_SECURITYMECHANISM
2993     * @see Property#DRDA_PROP_SECURITYMECHANISM
2994     */

2995    protected int getSecurityMechanism()
2996    {
2997        return allowOnlySecurityMechanism;
2998    }
2999    /**
3000     * Set the trace on/off for all sessions, or one session, depending on
3001     * whether we got -s argument.
3002     *
3003     * @param on true to turn trace on; false to turn it off
3004     * @return true if set false if an error occurred
3005     */

3006    private boolean setTrace(boolean on)
3007    {
3008        if (sessionArg == 0)
3009        {
3010            setTraceAll(on);
3011            synchronized(sessionTable) {
3012                for (Enumeration JavaDoc e = sessionTable.elements(); e.hasMoreElements(); )
3013                {
3014                    Session session = (Session) e.nextElement();
3015                    if (on)
3016                        session.setTraceOn(traceDirectory);
3017                    else
3018                        session.setTraceOff();
3019                }
3020            }
3021        }
3022        else
3023        {
3024            Session session = (Session) sessionTable.get(new Integer JavaDoc(sessionArg));
3025            if (session != null)
3026            {
3027                if (on)
3028                    session.setTraceOn(traceDirectory);
3029                else
3030                    session.setTraceOff();
3031            }
3032            else
3033                return false;
3034        }
3035        return true;
3036    }
3037
3038
3039    /**
3040     * Get the current value of the time slice
3041     *
3042     * @return time slice value
3043     */

3044    protected int getTimeSlice()
3045    {
3046            return timeSlice;
3047    }
3048    /**
3049     * Set the current value of time slice
3050     *
3051     * @param value time slice value
3052     * @exception Exception if value is < 0
3053     */

3054    private void setTimeSlice(int value)
3055        throws Exception JavaDoc
3056    {
3057        if (value < MIN_TIMESLICE)
3058            consolePropertyMessage("DRDA_InvalidValue.U", new String JavaDoc []
3059                {new Integer JavaDoc(value).toString(), "timeslice"});
3060        if (value == USE_DEFAULT)
3061            value = DEFAULT_TIMESLICE;
3062        synchronized(timeSliceSync) {
3063            timeSlice = value;
3064        }
3065    }
3066    
3067    /**
3068     * Get the current value of keepAlive to configure how long the server
3069     * should keep the socket alive for a disconnected client
3070     */

3071    protected boolean getKeepAlive()
3072    {
3073        return keepAlive;
3074    }
3075
3076    /**
3077     * Get the current value of minimum number of threads to create at start
3078     *
3079     * @return value of minimum number of threads
3080     */

3081    private int getMinThreads()
3082    {
3083        synchronized(threadsSync) {
3084            return minThreads;
3085        }
3086    }
3087    /**
3088     * Set the current value of minimum number of threads to create at start
3089     *
3090     * @param value value of minimum number of threads
3091     */

3092    private void setMinThreads(int value)
3093    {
3094        synchronized(threadsSync) {
3095            minThreads = value;
3096        }
3097    }
3098    /**
3099     * Get the current value of maximum number of threads to create
3100     *
3101     * @return value of maximum number of threads
3102     */

3103    private int getMaxThreads()
3104    {
3105        synchronized(threadsSync) {
3106            return maxThreads;
3107        }
3108    }
3109    /**
3110     * Set the current value of maximum number of threads to create
3111     *
3112     * @param value value of maximum number of threads
3113     * @exception Exception if value is less than 0
3114     */

3115    private void setMaxThreads(int value) throws Exception JavaDoc
3116    {
3117        if (value < MIN_MAXTHREADS)
3118            consolePropertyMessage("DRDA_InvalidValue.U", new String JavaDoc []
3119                {new Integer JavaDoc(value).toString(), "maxthreads"});
3120        if (value == USE_DEFAULT)
3121            value = DEFAULT_MAXTHREADS;
3122        synchronized(threadsSync) {
3123            maxThreads = value;
3124        }
3125    }
3126        
3127    /**
3128     * Get the current value of whether to trace all the sessions
3129     *
3130     * @return true if tracing is on for all sessions; false otherwise
3131     */

3132    protected boolean getTraceAll()
3133    {
3134        synchronized(traceAllSync) {
3135            return traceAll;
3136        }
3137    }
3138    /**
3139     * Set the current value of whether to trace all the sessions
3140     *
3141     * @param value true if tracing is on for all sessions; false otherwise
3142     */

3143    private void setTraceAll(boolean value)
3144    {
3145        synchronized(traceAllSync) {
3146            traceAll = value;
3147        }
3148    }
3149    /**
3150     * Get the current value of trace directory
3151     *
3152     * @return trace directory
3153     */

3154    protected String JavaDoc getTraceDirectory()
3155    {
3156        synchronized(traceDirectorySync) {
3157            return traceDirectory;
3158        }
3159    }
3160    /**
3161     * Set the current value of trace directory
3162     *
3163     * @param value trace directory
3164     */

3165    private void setTraceDirectory(String JavaDoc value)
3166    {
3167        synchronized(traceDirectorySync) {
3168            traceDirectory = value;
3169        }
3170    }
3171
3172    
3173
3174    /**
3175     * Connect to a database to test whether a connection can be made
3176     *
3177     * @param writer connection to send message to
3178     * @param database database directory to connect to
3179     * @param user user to use
3180     * @param password password to use
3181     */

3182    private void connectToDatabase(DDMWriter writer, String JavaDoc database, String JavaDoc user,
3183        String JavaDoc password) throws Exception JavaDoc
3184    {
3185        Properties JavaDoc p = new Properties JavaDoc();
3186        if (user != null)
3187            p.put("user", user);
3188        if (password != null)
3189            p.put("password", password);
3190        try {
3191            Class.forName(CLOUDSCAPE_DRIVER);
3192        }
3193        catch (Exception JavaDoc e) {
3194            sendMessage(writer, ERROR, e.getMessage());
3195            return;
3196        }
3197        try {
3198            //Note, we add database to the url so that we can allow additional
3199
//url attributes
3200
Connection JavaDoc conn = DriverManager.getConnection(Attribute.PROTOCOL+database, p);
3201            // send warnings
3202
SQLWarning JavaDoc warn = conn.getWarnings();
3203            if (warn != null)
3204                sendSQLMessage(writer, warn, SQLWARNING);
3205            else
3206                sendOK(writer);
3207            conn.close();
3208            return;
3209        } catch (SQLException JavaDoc se) {
3210            sendSQLMessage(writer, se, SQLERROR);
3211        }
3212    }
3213    /**
3214     * Boot database
3215     *
3216     * @param writer connection to send message to
3217     * @param database database directory to connect to
3218     * @param bootPassword boot password
3219     * @param encPrv encryption provider
3220     * @param encAlg encryption algorithm
3221     * @param user user to use
3222     * @param password password to use
3223     */

3224    private void startDatabase(DDMWriter writer, String JavaDoc database,
3225        String JavaDoc bootPassword, String JavaDoc encPrv, String JavaDoc encAlg, String JavaDoc user,
3226            String JavaDoc password) throws Exception JavaDoc
3227    {
3228        Properties JavaDoc p = new Properties JavaDoc();
3229        if (bootPassword != null)
3230            p.put(Attribute.BOOT_PASSWORD, bootPassword);
3231        if (encPrv != null)
3232            p.put(Attribute.CRYPTO_PROVIDER, encPrv);
3233        if (encAlg != null)
3234            p.put(Attribute.CRYPTO_ALGORITHM, encAlg);
3235        if (user != null)
3236            p.put(Attribute.USERNAME_ATTR, user);
3237        if (password != null)
3238            p.put(Attribute.PASSWORD_ATTR, password);
3239        try {
3240            Class.forName(CLOUDSCAPE_DRIVER);
3241        }
3242        catch (Exception JavaDoc e) {
3243            sendMessage(writer, ERROR, e.getMessage());
3244            return;
3245        }
3246        try {
3247            //Note, we add database to the url so that we can allow additional
3248
//url attributes
3249
Connection JavaDoc conn = DriverManager.getConnection(Attribute.PROTOCOL+database, p);
3250            SQLWarning JavaDoc warn = conn.getWarnings();
3251            if (warn != null)
3252                sendSQLMessage(writer, warn, SQLWARNING);
3253            else
3254                sendOK(writer);
3255            conn.close();
3256        } catch (SQLException JavaDoc se) {
3257            sendSQLMessage(writer, se, SQLERROR);
3258        } catch (Exception JavaDoc e) {
3259            sendMessage(writer, ERROR, e.getMessage());
3260        }
3261    }
3262    /**
3263     * Shutdown a database
3264     *
3265     * @param writer connection to send message to
3266     * @param database database directory to shutdown to
3267     * @param user user to use
3268     * @param password password to use
3269     */

3270    private void shutdownDatabase(DDMWriter writer, String JavaDoc database, String JavaDoc user,
3271        String JavaDoc password) throws Exception JavaDoc
3272    {
3273
3274        StringBuffer JavaDoc url = new StringBuffer JavaDoc(Attribute.PROTOCOL + database);
3275        if (user != null)
3276            url.append(";user="+user);
3277        if (password != null)
3278            url.append(";password="+password);
3279        url.append(";shutdown=true");
3280        try {
3281            Class.forName(CLOUDSCAPE_DRIVER);
3282        }
3283        catch (Exception JavaDoc e) {
3284            sendMessage(writer, ERROR, e.getMessage());
3285            return;
3286        }
3287        try {
3288            Connection JavaDoc conn = DriverManager.getConnection(url.toString());
3289            SQLWarning JavaDoc warn = conn.getWarnings();
3290            if (warn != null)
3291                sendSQLMessage(writer, warn, SQLWARNING);
3292            else
3293                sendOK(writer);
3294            conn.close();
3295        } catch (SQLException JavaDoc se) {
3296            //ignore shutdown error
3297
String JavaDoc expectedState =
3298                StandardException.
3299                    getSQLStateFromIdentifier(SQLState.SHUTDOWN_DATABASE);
3300            if (!expectedState.equals(se.getSQLState()))
3301            {
3302                sendSQLMessage(writer, se, SQLERROR);
3303                return;
3304            }
3305            sendOK(writer);
3306        }
3307    }
3308    /**
3309     * Wrap SQL Error - display to console and raise exception
3310     *
3311     * @param messageKey Cloudscape SQL Exception message id
3312     *
3313     * @exception Exception raises exception for message
3314     */

3315    private void wrapSQLError(String JavaDoc messageKey)
3316        throws Exception JavaDoc
3317    {
3318        consolePropertyMessage("DRDA_SQLException.S", messageKey);
3319    }
3320
3321    /**
3322     * Wrap SQL Warning - display to console and raise exception
3323     *
3324     * @param messageKey Cloudscape SQL Exception message id
3325     *
3326     * @exception Exception raises exception for message
3327     */

3328    private void wrapSQLWarning(String JavaDoc messageKey)
3329        throws Exception JavaDoc
3330    {
3331        consolePropertyMessage("DRDA_SQLWarning.I", messageKey);
3332    }
3333    private Properties JavaDoc getPropertyValues()
3334    {
3335        Properties JavaDoc retval = new Properties JavaDoc();
3336        retval.put(Property.DRDA_PROP_PORTNUMBER, new Integer JavaDoc(portNumber).toString());
3337        retval.put(Property.DRDA_PROP_HOSTNAME, hostArg);
3338        retval.put(Property.DRDA_PROP_KEEPALIVE, new Boolean JavaDoc(keepAlive).toString());
3339
3340        String JavaDoc tracedir = getTraceDirectory();
3341        if (tracedir != null)
3342            retval.put(Property.DRDA_PROP_TRACEDIRECTORY, tracedir);
3343        retval.put(Property.DRDA_PROP_TRACEALL, new Boolean JavaDoc(getTraceAll()).toString());
3344        retval.put(Property.DRDA_PROP_MINTHREADS, new Integer JavaDoc(getMinThreads()).toString());
3345        retval.put(Property.DRDA_PROP_MAXTHREADS, new Integer JavaDoc(getMaxThreads()).toString());
3346        retval.put(Property.DRDA_PROP_TIMESLICE, new Integer JavaDoc(getTimeSlice()).toString());
3347
3348        retval.put(Property.DRDA_PROP_TIMESLICE, new Integer JavaDoc(getTimeSlice()).toString());
3349        retval.put(Property.DRDA_PROP_LOGCONNECTIONS, new Boolean JavaDoc(getLogConnections()).toString());
3350        String JavaDoc startDRDA = PropertyUtil.getSystemProperty(Property.START_DRDA);
3351        //DERBY-375 If a system property is specified without any value, getProperty returns
3352
//an empty string. Use default values in such cases.
3353
if(startDRDA!=null && startDRDA.equals(""))
3354            startDRDA = "false";
3355        
3356        retval.put(Property.START_DRDA, (startDRDA == null)? "false" : startDRDA);
3357
3358        // if Property.DRDA_PROP_SECURITYMECHANISM has been set on server
3359
// then put it in retval else the default behavior is as though
3360
// it is not set
3361
if ( getSecurityMechanism() != INVALID_OR_NOTSET_SECURITYMECHANISM )
3362            retval.put( Property.DRDA_PROP_SECURITYMECHANISM, getStringValueForSecMec(getSecurityMechanism()));
3363        
3364        //get the trace value for each session if tracing for all is not set
3365
if (!getTraceAll())
3366        {
3367            synchronized(sessionTable) {
3368                for (Enumeration JavaDoc e = sessionTable.elements(); e.hasMoreElements(); )
3369                {
3370                    Session session = (Session) e.nextElement();
3371                    if (session.isTraceOn())
3372                        retval.put(Property.DRDA_PROP_TRACE+"."+session.getConnNum(), "true");
3373                }
3374            }
3375        }
3376        return retval;
3377    }
3378
3379
3380    /**
3381     * Add a session - for use by <code>ClientThread</code>. Put the session
3382     * into the session table and the run queue. Start a new
3383     * <code>DRDAConnThread</code> if there are more sessions waiting than
3384     * there are free threads, and the maximum number of threads is not
3385     * exceeded.
3386     *
3387     * <p><code>addSession()</code> should only be called from one thread at a
3388     * time.
3389     *
3390     * @param clientSocket the socket to read from and write to
3391     */

3392    void addSession(Socket JavaDoc clientSocket) throws Exception JavaDoc {
3393
3394        int connectionNumber = ++connNum;
3395
3396        if (getLogConnections()) {
3397            consolePropertyMessage("DRDA_ConnNumber.I",
3398                                   Integer.toString(connectionNumber));
3399        }
3400
3401        // Note that we always re-fetch the tracing configuration because it
3402
// may have changed (there are administrative commands which allow
3403
// dynamic tracing reconfiguration).
3404
Session session = new Session(connectionNumber, clientSocket,
3405                                      getTraceDirectory(), getTraceAll());
3406
3407        sessionTable.put(new Integer JavaDoc(connectionNumber), session);
3408
3409        // Check whether there are enough free threads to service all the
3410
// threads in the run queue in addition to the newly added session.
3411
boolean enoughThreads;
3412        synchronized (runQueue) {
3413            enoughThreads = (runQueue.size() < freeThreads);
3414        }
3415        // No need to hold the synchronization on runQueue any longer than
3416
// this. Since no other threads can make runQueue grow, and no other
3417
// threads will reduce the number of free threads without removing
3418
// sessions from runQueue, (runQueue.size() < freeThreads) cannot go
3419
// from true to false until addSession() returns.
3420

3421        DRDAConnThread thread = null;
3422
3423        // try to start a new thread if we don't have enough free threads
3424
if (!enoughThreads) {
3425            // Synchronize on threadsSync to ensure that the value of
3426
// maxThreads doesn't change until the new thread is added to
3427
// threadList.
3428
synchronized (threadsSync) {
3429                // only start a new thread if we have no maximum number of
3430
// threads or the maximum number of threads is not exceeded
3431
if ((maxThreads == 0) || (threadList.size() < maxThreads)) {
3432                    thread = new DRDAConnThread(session, this, getTimeSlice(),
3433                                                getLogConnections());
3434                    threadList.add(thread);
3435                    thread.start();
3436                }
3437            }
3438        }
3439
3440        // add the session to the run queue if we didn't start a new thread
3441
if (thread == null) {
3442            runQueueAdd(session);
3443        }
3444    }
3445
3446    /**
3447     * Remove a thread from the thread list. Should be called when a
3448     * <code>DRDAConnThread</code> has been closed.
3449     *
3450     * @param thread the closed thread
3451     */

3452    void removeThread(DRDAConnThread thread) {
3453        threadList.remove(thread);
3454    }
3455    
3456    protected Object JavaDoc getShutdownSync() { return shutdownSync; }
3457    protected boolean getShutdown() { return shutdown; }
3458
3459
3460    public String JavaDoc buildRuntimeInfo(LocalizedResource locallangUtil)
3461    {
3462        
3463        String JavaDoc s = locallangUtil.getTextMessage("DRDA_RuntimeInfoBanner.I")+ "\n";
3464        int sessionCount = 0;
3465        s += locallangUtil.getTextMessage("DRDA_RuntimeInfoSessionBanner.I") + "\n";
3466        for (int i = 0; i < threadList.size(); i++)
3467        {
3468            String JavaDoc sessionInfo = ((DRDAConnThread)
3469                                   threadList.get(i)).buildRuntimeInfo("",locallangUtil) ;
3470            if (!sessionInfo.equals(""))
3471            {
3472                sessionCount ++;
3473                s += sessionInfo + "\n";
3474            }
3475        }
3476        int waitingSessions = 0;
3477        for (int i = 0; i < runQueue.size(); i++)
3478        {
3479                s += ((Session)runQueue.get(i)).buildRuntimeInfo("", locallangUtil);
3480                waitingSessions ++;
3481        }
3482        s+= "-------------------------------------------------------------\n";
3483        s += locallangUtil.getTextMessage("DRDA_RuntimeInfoNumThreads.I") +
3484            threadList.size() + "\n";
3485        s += locallangUtil.getTextMessage("DRDA_RuntimeInfoNumActiveSessions.I") +
3486            sessionCount +"\n";
3487        s +=locallangUtil.getTextMessage("DRDA_RuntimeInfoNumWaitingSessions.I") +
3488            + waitingSessions + "\n\n";
3489
3490        Runtime JavaDoc rt = Runtime.getRuntime();
3491        rt.gc();
3492        long totalmem = rt.totalMemory();
3493        long freemem = rt.freeMemory();
3494        s += locallangUtil.getTextMessage("DRDA_RuntimeInfoTotalMemory.I") +
3495            + totalmem + "\t";
3496        s += locallangUtil.getTextMessage("DRDA_RuntimeInfoFreeMemory.I") +
3497            + freemem + "\n\n";
3498        
3499        return s;
3500    }
3501
3502
3503    protected void setClientLocale(String JavaDoc locale)
3504    {
3505        clientLocale = locale;
3506    }
3507
3508    /**
3509     * Retrieve product version information
3510     * We need to make sure that this method gets the stream and passes it to
3511     * ProductVersionHolder, because it lives in the Network Server jar
3512     * and won't be readily available to ProductVersionHolder when running
3513     * under security manager.
3514     */

3515    private ProductVersionHolder getNetProductVersionHolder() throws Exception JavaDoc
3516    {
3517        ProductVersionHolder myPVH= null;
3518        try {
3519            myPVH = (ProductVersionHolder) AccessController.doPrivileged(
3520                                new PrivilegedExceptionAction JavaDoc() {
3521                                        
3522                                    public Object JavaDoc run() throws UnknownHostException JavaDoc,IOException JavaDoc
3523                                    {
3524                                        InputStream JavaDoc versionStream = getClass().getResourceAsStream(ProductGenusNames.NET_INFO);
3525
3526                                        return ProductVersionHolder.getProductVersionHolderFromMyEnv(versionStream);
3527                                    }
3528                                    });
3529        
3530}
3531        catch(PrivilegedActionException JavaDoc e) {
3532            Exception JavaDoc e1 = e.getException();
3533            consolePropertyMessage("DRDA_ProductVersionReadError.S", e1.getMessage());
3534        }
3535        return myPVH;
3536    }
3537
3538    /**
3539     * This method returns a timestamp to be used in the messages.
3540     * CheapDateFormatter class, which uses GMT, is used to format timestamps.
3541     * This is to keep the formatting consistent with Derby boot message since
3542     * network server messages and the boot message get written to derby.log.
3543     *
3544     * @return current timestamp formatted in GMT
3545     */

3546    private String JavaDoc getFormattedTimestamp(){
3547        long currentTime = System.currentTimeMillis();
3548        return CheapDateFormatter.formatDate(currentTime);
3549    }
3550}
3551
3552
3553
3554
3555
3556
3557
Popular Tags