KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > uk > org > primrose > pool > jmx > PoolController


1 /**
2 * Library name : Primrose - A Java Database Connection Pool.
3 * Published by Ben Keeping, http://primrose.org.uk .
4 * Copyright (C) 2004 Ben Keeping, primrose.org.uk
5 * Email: Use "Contact Us Form" on website
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */

21
22 package uk.org.primrose.pool.jmx;
23 import com.sun.jdmk.comm.*;
24 import javax.management.*;
25 import javax.management.loading.*;
26 import javax.management.remote.*;
27 import javax.management.monitor.*;
28 import java.util.*;
29 import java.io.*;
30 import java.sql.ResultSet JavaDoc;
31 import java.sql.SQLException JavaDoc;
32 import java.lang.reflect.*;
33 import javax.naming.Context JavaDoc;
34 import javax.naming.InitialContext JavaDoc;
35 import uk.org.primrose.pool.datasource.PoolDataSource;
36 import uk.org.primrose.pool.jmx.html.*;
37 import javax.management.openmbean.*;
38
39 public class PoolController extends NotificationBroadcasterSupport implements PoolControllerMBean {//, DynamicMBean {
40
private static MBeanServer _server;
41     protected static HtmlAdaptorServer _html;
42     private static MBeanInfo _MBeanInfo;
43     private static PoolController controller;
44     public static final String JavaDoc CONTROLLER_OBJECT_NAME = "PoolController Domain:name=PoolController";
45     public static final String JavaDoc POOL_QUEUE_OBJECT_NAME = "Pool Domain";
46     private ArrayList _mbeans = new ArrayList();
47     private ArrayList _queues = new ArrayList();
48     private ArrayList pools = new ArrayList();
49     PoolControllerListener listener = null;
50     private Context JavaDoc ctx = null;
51     private String JavaDoc[] email = null;
52     private String JavaDoc poolConfigFile = "";
53     private String JavaDoc adminWebManagementPort = "-1";
54     private boolean emailNotifications = true;
55     private String JavaDoc adminUser = "admin";
56     private String JavaDoc adminPassword = "admin";
57     private int emailMaxWarningNumber = 10;
58     private long emailNotificationPeriod = 30000;
59     private String JavaDoc emailSMTPServer = "";
60     private String JavaDoc adminEmailCrisisAddress = "";
61     private AllPoolsOverview allPoolOverviewBean = null;
62     private String JavaDoc poolControllerLogFile = null;
63     private ObjectMonitor lastModifiedMonitor = null;
64
65     //////////////////////////////////////////////////////////////////////////////////////
66
/** main functional/operational methods **/
67     //////////////////////////////////////////////////////////////////////////////////////
68

69     public String JavaDoc createNewPoolQueue(String JavaDoc poolName, Integer JavaDoc base, Integer JavaDoc overflow, String JavaDoc plog,
70                                      Integer JavaDoc idleTime, Boolean JavaDoc messageLogging, Boolean JavaDoc sizeLogging,
71                                      String JavaDoc driverClass, String JavaDoc driverURL, String JavaDoc user, String JavaDoc password,
72                                      String JavaDoc killActiveConnectionsOverAge, String JavaDoc cycleConnections, Boolean JavaDoc queueConnectionRequests,
73                                      Boolean JavaDoc runPooledMode, Boolean JavaDoc connectionAutoCommit, String JavaDoc connectionTransactionIsolation, String JavaDoc checkSQL) {
74             Properties props = new Properties();
75             props.setProperty("poolName", poolName);
76             props.setProperty("base", base+"");
77             props.setProperty("overflow", overflow +"");
78             props.setProperty("plog", plog);
79             props.setProperty("idleTime", idleTime +"");
80             props.setProperty("messageLogging", messageLogging +"");
81             props.setProperty("sizeLogging", sizeLogging +"");
82             props.setProperty("driverClass", driverClass);
83             props.setProperty("driverURL", driverURL);
84             props.setProperty("user", user);
85             props.setProperty("password", password);
86             props.setProperty("killActiveConnectionsOverAge", killActiveConnectionsOverAge);
87             props.setProperty("cycleConnections", cycleConnections);
88             props.setProperty("queueConnectionRequests", queueConnectionRequests +"");
89             props.setProperty("runPooledMode", runPooledMode +"");
90             props.setProperty("connectionAutoCommit", connectionAutoCommit +"");
91             props.setProperty("connectionTransactionIsolation", connectionTransactionIsolation);
92             props.setProperty("checkSQL", checkSQL);
93
94             return createNewPoolQueue(props);
95     }
96
97
98     public String JavaDoc createNewPoolQueue(Properties props) {
99
100         // TODO :If we get here and the log is null, it means
101
// they have not loaded any admin settings, so create them a default one
102
//if (log == null) {
103
// System.out.println("\n\n-------------------------------------------\n" +
104
// "[PoolController] WARNING !!!\n\tYou are trying to load a pool without loading any admin details\n" +
105
// "\tAs of v2.6.1, this is not allowed, you must load a Properties object that contains \n"+
106
// "\tsome admin details (at the very least, a PoolController log file location), eg :\n" +
107
// "\t\t\tadminPoolControllerLogFile=/var/log/PoolController.log\n" +
108
// "\tThis should be added in the \"admin\" section, not the pool instance section.\n" +
109
// "\tIf you want to run the admin controller in silent mode (ie no logging), then set value 'none'\n" +
110
// "\tFor now, we'll continue loading, but with a default log (./PoolController.log) ... \n\tplease change this in the future !" +
111
// "\n\n-------------------------------------------\n\n\n");
112
// setPoolControllerLogFile("./PoolController.log");
113

114         //}
115

116         Object JavaDoc tmpProp = null;
117         // Set the pool / queue name
118
tmpProp = props.getProperty("poolName");
119         String JavaDoc poolName = (tmpProp == null ? "noPoolNameSet" : (String JavaDoc)tmpProp);
120         //ControllerLogger.log("[PoolController] Creating new pool - " +poolName +" " +driverURL+" " +plog +" " +base +" " +overflow +" " +idleTime +" " +messageLogging +" " +sizeLogging +" " +killActiveConnectionsOverAge +" " +cycleConnections +" " +queueConnectionRequests);
121
ControllerLogger.log("[PoolController] Creating new pool - " +poolName);
122
123
124         // Set the db password
125
// If there is a pool.keys file in the directory next
126
// to the config file, then assume they wish to have
127
// encrypted passwords.
128
// If this is the case, then decrypt the password ready to
129
// load the pools with.
130
tmpProp = props.getProperty("password");
131         String JavaDoc password = (tmpProp == null ? "" : (String JavaDoc)tmpProp);
132
133         tmpProp = props.getProperty("encryptionKeyFile");
134         String JavaDoc encryptionKeyFile = (tmpProp == null ? "" : (String JavaDoc)tmpProp);
135
136         if (this.getPoolConfigFile() != null || encryptionKeyFile != null) {
137             File f;
138             if (this.getPoolConfigFile() != null) {
139                     File pcf = new File(this.getPoolConfigFile());
140                 String JavaDoc parentFileName = pcf.getParentFile().toString();
141                 if (parentFileName == null) {
142                     parentFileName = ".";
143                 }
144                     f = new File(parentFileName +File.separator +"pool.keys");
145             } else {
146                 f = new File(encryptionKeyFile);
147             }
148                 if (f.exists()) {
149                 try {
150                     ControllerLogger.log("[PoolController] Decrypting '" +password +"' using file " +f);
151                     password = new PoolCryptoTool().getDecryptedString(password, f.toString());
152                     props.setProperty("password", password);
153                 } catch (Exception JavaDoc e) {
154                     e.printStackTrace(System.err);
155                     ControllerLogger.log("[PoolController] ERROR : Cannot load pool because decryption of the password failed. See stderr for full stack trace. Tryed to load file : " +f);
156                     return null;
157                 }
158
159             } else {
160                 ControllerLogger.log("[PoolController] INFO : Not using password encryption for db's because cannot find file : " +f.toString());
161             }
162         }
163
164         try {
165             ObjectName objName = null;
166             MBeanServer mbs = null;
167
168             // find reference to (or create) MBean server
169
mbs = MBeanUtil.getMBeanServer(_server);
170
171             // For some reason Tomcat5's MBeanServer ClassLoader cannot find our Queue
172
// class - I expect some bug in Tomcat5, or a different CLASSPATH for the JVM
173
// ClassLoader. Maybe because JMX relies on RMI quite heavily - which has a
174
// spearate ClassLoader path as to the normal CLASSPATH.
175
// Works in Tomcat4 though !
176
// Anyway, a fix is not to load the class via the MBEanServer, but
177
// to instantiate one ourselves, and then register it with the MBeanServer
178
// as normal.
179

180             // String queueClassName = "uk.org.primrose.pool.jmx.Queue";
181
// Object queue = mbs.instantiate(queueClassName);
182
// Queue _queue = (Queue)queue;
183

184             Queue _queue = new Queue();
185
186             // Start a new pool with the given properties
187
_queue.startNewPool(props);
188
189             // Register the pool queue with the MBean server
190
objName = new ObjectName(POOL_QUEUE_OBJECT_NAME + ":name=Queue,pool=" +poolName);
191             MBeanUtil.registerMBean(_server, _queue, objName);
192
193             // Add our objects to our private lists
194
_mbeans.add(objName);
195             _queues.add(_queue);
196
197             // Register the pool with the datasource
198
PoolDataSource pds = new PoolDataSource();
199             pds.setPoolName(poolName);
200
201             // And bind the queue, and the datasource into
202
// the JNDI context
203
MBeanUtil.bind("q_" +poolName, _queue);
204             MBeanUtil.bind(poolName, pds);
205             ControllerLogger.log("[PoolController] DataSource " +pds +" bound to javax.naming.Context " +poolName);
206
207             // Notify that the pools are coming up
208
AttributeChangeNotification acn = new AttributeChangeNotification(this,
209                                 0,
210                                 System.currentTimeMillis(),
211                                 //"[PoolController] Creating new pool - " +poolName +" " +driverURL +" " +plog +" " +base +" " +overflow +" " +idleTime + " " +messageLogging +" " +sizeLogging +" " +killActiveConnectionsOverAge +" " +cycleConnections,
212
("[PoolController] Creating new pool - " +poolName),
213                                 "[PoolController] createNewPoolQueue",
214                                 "",
215                                 null,
216                                 null);
217             sendNotification(acn);
218
219             // Set up the pool monitors :
220
// - the number of waiting connections
221
// - for removing idle/unused connections
222
// - the log cycler
223
// - for killing off connetions that are active for too long
224

225             // Create a monitor for the threads
226
ObjectMonitor omonitor = new ObjectMonitor();
227             omonitor.setName(poolName);
228             omonitor.setObservedObject(_queue);
229             omonitor.setObservedMethod("getWaitingThreads", null);
230             omonitor.setCheckValue("5");
231             omonitor.setIncrementThreshold(true);
232             omonitor.setObservedMethodNotificationType(ObjectMonitor.THRESHOLD);
233             omonitor.setRefreshInterval(5000);
234             ObjectName monObjName = new ObjectName("Pool Monitor:name=ObjectMonitor([" +poolName +"] waiting threads)");
235
236             MBeanUtil.registerMBean(_server, omonitor, monObjName);
237             _server.addNotificationListener(monObjName, listener, null, null);
238             omonitor.start();
239             _queue.registerNewObjectMonitor(omonitor);
240             _mbeans.add(monObjName);
241
242             // Create a monitor for the idle connections
243
tmpProp = props.getProperty("idleTime");
244             String JavaDoc idleTime = (tmpProp == null ? "-1" : (String JavaDoc)tmpProp);
245
246             if (!(idleTime.equals("-1"))) {
247                 ObjectMonitor omonitor2 = new ObjectMonitor();
248                 omonitor2.setName(poolName);
249                 omonitor2.setObservedObject(_queue);
250                 omonitor2.setObservedMethod("checkIdleConnections", null);
251                 omonitor2.setCheckValue("5");
252                 omonitor2.setIncrementThreshold(false);
253                 omonitor2.setObservedMethodNotificationType(ObjectMonitor.THRESHOLD);
254                 omonitor2.setRefreshInterval(10000);
255                 monObjName = new ObjectName("Pool Monitor:name=ObjectMonitor([" +poolName +"] idle connections)");
256                 MBeanUtil.registerMBean(_server, omonitor2, monObjName);
257                 _server.addNotificationListener(monObjName, listener, null, null);
258                 omonitor2.start();
259                 _queue.registerNewObjectMonitor(omonitor2);
260                 _mbeans.add(monObjName);
261             }
262
263             // Set up the log monitor- this can be null !
264
// If it is not null, then set up the monitor bean
265
// which will cycle the logs
266
tmpProp = props.getProperty("log");
267             String JavaDoc plog = (tmpProp == null ? null : (String JavaDoc)tmpProp);
268
269             if (plog != null) {
270                 if (plog.indexOf("${") != -1) {
271                     // Create a monitor for the pool logging
272
ObjectMonitor omonitor3 = new ObjectMonitor();
273                     omonitor3.setName(poolName);
274                     omonitor3.setObservedObject(_queue);
275                     omonitor3.setObservedMethod("setUpLog", null);
276                     omonitor3.setCheckValue("0");
277                     omonitor3.setIncrementThreshold(true);
278                     omonitor3.setObservedMethodNotificationType(ObjectMonitor.DIFFERING);
279                     omonitor3.setRefreshInterval(60000);
280                     monObjName = new ObjectName("Pool Monitor:name=ObjectMonitor([" +poolName +"] pool log cycling)");
281                     MBeanUtil.registerMBean(_server, omonitor3, monObjName);
282                     _server.addNotificationListener(monObjName, listener, null, null);
283                     omonitor3.start();
284                     _queue.registerNewObjectMonitor(omonitor3);
285                     _mbeans.add(monObjName);
286                 }
287             }
288
289             // Create a monitor for the active connections
290
// if specified in the config file
291
// Set the time connections have till they are timed out (killed)
292
tmpProp = props.getProperty("killActiveConnectionsOverAge");
293             String JavaDoc killActiveConnectionsOverAge = (tmpProp == null ? "-1" : (String JavaDoc)tmpProp);
294
295             if (!(killActiveConnectionsOverAge.equals("-1"))) {
296                 ObjectMonitor omonitor4 = new ObjectMonitor();
297                 omonitor4.setName(poolName);
298                 omonitor4.setObservedObject(_queue);
299                 omonitor4.setObservedMethod("checkActiveConnectionTimes", null);
300                 omonitor4.setCheckValue("5");
301                 omonitor4.setIncrementThreshold(false);
302                 omonitor4.setObservedMethodNotificationType(ObjectMonitor.THRESHOLD);
303                 omonitor4.setRefreshInterval(5000);
304                 monObjName = new ObjectName("Pool Monitor:name=ObjectMonitor([" +poolName +"] active connections kill daemon)");
305                 MBeanUtil.registerMBean(_server, omonitor4, monObjName);
306                 _server.addNotificationListener(monObjName, listener, null, null);
307                 omonitor4.start();
308                 _queue.registerNewObjectMonitor(omonitor4);
309                 _mbeans.add(monObjName);
310             }
311
312
313             allPoolOverviewBean.addPoolData(_queue);
314
315         } catch (Exception JavaDoc e) {
316             e.printStackTrace();
317             ControllerLogger.log(e.toString());
318             return "ERROR";
319         }
320
321
322         return poolName +" successfully started.";
323
324     }
325
326     /**
327     * Return a list of registered pool queues.
328     */

329     public ArrayList getQueues() {
330         return this._queues;
331     }
332
333     /**
334     * Given a pool queue name to look up, query the mbean server
335     * for that registed Queue object.
336     */

337     public Queue getQueue(String JavaDoc queueName) {
338         Queue queue = null;
339         try {
340             MBeanServer mbs = MBeanUtil.getMBeanServer(_server);
341             ObjectName name = new ObjectName(POOL_QUEUE_OBJECT_NAME + ":name=Queue,pool=" +queueName);
342             QueryExp query = null;
343             Iterator results = (mbs.queryMBeans(name, query)).iterator();
344
345             while (results.hasNext()) {
346                 ObjectName on = ((ObjectInstance)results.next()).getObjectName();
347                 ControllerLogger.log("[PoolController] Locked to : " +on.toString());
348                 for (int i = 0; i < _queues.size(); i++) {
349                     queue = (Queue)_queues.get(i);
350                     if (queue.getName().equals(queueName)) {
351                         ControllerLogger.log("[PoolController] Queue found : " +queue +" " +queue.getName());
352                         return queue;
353                     }
354                 }
355
356             }
357         } catch (Exception JavaDoc e) {
358             e.printStackTrace(System.err);
359         }
360
361         return null;
362     }
363
364     /**
365     * Start all the pools
366     */

367     public void startAllPoolQueues() {
368         ObjectName on = null;
369         Queue queue = null;
370         String JavaDoc q = "";
371         try {
372             MBeanServer mbs = MBeanUtil.getMBeanServer(_server);
373             ObjectName name = new ObjectName(POOL_QUEUE_OBJECT_NAME + ":*");
374             QueryExp query = null;
375             Iterator results = (mbs.queryMBeans(name, query)).iterator();
376             while (results.hasNext()) {
377                 on = ((ObjectInstance)results.next()).getObjectName();
378                 ControllerLogger.log("[PoolController] Locked to : " +on.toString());
379                 for (int i = 0; i < _queues.size(); i++) {
380                     queue = (Queue)_queues.get(i);
381                     if (on.toString().indexOf(queue.getName()) != -1) {
382                         queue.startPool();
383                         q += (on +" " +queue +"\n");
384                     }
385                 }
386
387             }
388             AttributeChangeNotification acn = new AttributeChangeNotification(this,
389                                 0,
390                                 System.currentTimeMillis(),
391                                 q,
392                                 "[PoolController] startAllPoolQueues",
393                                 "",
394                                 null,
395                                 null);
396             sendNotification(acn);
397         } catch (Exception JavaDoc e) {
398             ControllerLogger.log("[PoolController] : ERROR: " + "Error stoppping pool queue MBean " +on +" " +queue +" !");
399             e.printStackTrace();
400         }
401     }
402
403     /**
404     * Stop all the pools
405     */

406     public void stopAllPoolQueues() {
407         ObjectName on = null;
408         Queue queue = null;
409         String JavaDoc q = "";
410         if (lastModifiedMonitor != null) lastModifiedMonitor.stop();
411         try {
412             MBeanServer mbs = MBeanUtil.getMBeanServer(_server);
413             ObjectName name = new ObjectName(POOL_QUEUE_OBJECT_NAME + ":*");
414             QueryExp query = null;
415             Iterator results = (mbs.queryMBeans(name, query)).iterator();
416             while (results.hasNext()) {
417                 on = ((ObjectInstance)results.next()).getObjectName();
418                 ControllerLogger.log("[PoolController] Locked to : " +on.toString());
419                 for (int i = 0; i < _queues.size(); i++) {
420                     queue = (Queue)_queues.get(i);
421                     if (on.toString().indexOf(queue.getName()) != -1) {
422                         queue.stopPool();
423                         q += (on +" " +queue +"\n");
424                     }
425                 }
426
427             }
428             AttributeChangeNotification acn = new AttributeChangeNotification(this,
429                                 0,
430                                 System.currentTimeMillis(),
431                                 q,
432                                 "[PoolController] stopAllPoolQueues",
433                                 "",
434                                 null,
435                                 null);
436             sendNotification(acn);
437         } catch (Exception JavaDoc e) {
438             ControllerLogger.log("[PoolController] : ERROR: " + "Error stoppping pool queue MBean " +on +" " +queue +" !");
439             e.printStackTrace();
440         }
441     }
442
443     /**
444     * Stop, and then start all the pools
445     */

446     public void reset() {
447         stopAllPoolQueues();
448         try { Thread.sleep(1000); } catch (Exception JavaDoc e) {}
449         startAllPoolQueues();
450
451     }
452
453     /**
454     * Convenient method to restart an (already bound) pool.
455     */

456     public static boolean restartSinglePool(String JavaDoc poolName) {
457         ControllerLogger.log("[PoolController] Got request to restart single pool queue : " +poolName);
458         Queue queue = controller.getQueue(poolName);
459         if (queue == null) {
460             ControllerLogger.log("[PoolController] Cannot locate pool queue under name : " +poolName);
461             return false;
462         }
463
464         String JavaDoc n = queue.getName();
465         ControllerLogger.log("[PoolController] Stopping pool : " +n);
466         queue.stopPool();
467         try { Thread.sleep(1000); } catch (Exception JavaDoc e) {}
468         ControllerLogger.log("[PoolController] Starting pool : " +n);
469         queue.startPool();
470
471         AttributeChangeNotification acn = new AttributeChangeNotification(controller,
472                             0,
473                             System.currentTimeMillis(),
474                             "restartSinglePool(" +poolName +")",
475                             "[PoolController] restarted pool : " +poolName,
476                             "",
477                             null,
478                             null);
479         controller.sendNotification(acn);
480         return true;
481     }
482
483     /**
484      * Convenient method to start an (already bound) pool. The pool must already be bound - this is not a way to bind fresh new pools.
485      *
486      */

487     public static boolean startSinglePool(String JavaDoc poolName) {
488         ControllerLogger.log("[PoolController] Got request to start single pool queue : " +poolName);
489         Queue queue = controller.getQueue(poolName);
490         if (queue == null) {
491             ControllerLogger.log("[PoolController] Cannot locate pool queue under name : " +poolName);
492             return false;
493         }
494
495         String JavaDoc n = queue.getName();
496         ControllerLogger.log("[PoolController] Starting pool : " +n);
497         queue.startPool();
498
499         AttributeChangeNotification acn = new AttributeChangeNotification(controller,
500                             0,
501                             System.currentTimeMillis(),
502                             "startSinglePool(" +poolName +")",
503                             "[PoolController] Started pool : " +poolName,
504                             "",
505                             null,
506                             null);
507         controller.sendNotification(acn);
508         return true;
509     }
510
511     /**
512      * Convenient method to stop an (already bound) pool. This will dump all connections.
513      *
514      */

515     public static boolean stopSinglePool(String JavaDoc poolName) {
516         ControllerLogger.log("[PoolController] Got request to stop single pool queue : " +poolName);
517         Queue queue = controller.getQueue(poolName);
518         if (queue == null) {
519             ControllerLogger.log("[PoolController] Cannot locate pool queue under name : " +poolName);
520             return false;
521         }
522
523         String JavaDoc n = queue.getName();
524         ControllerLogger.log("[PoolController] Stopping pool : " +n);
525         queue.stopPool();
526
527         AttributeChangeNotification acn = new AttributeChangeNotification(controller,
528                             0,
529                             System.currentTimeMillis(),
530                             "stopSinglePool(" +poolName +")",
531                             "[PoolController] stopped pool : " +poolName,
532                             "",
533                             null,
534                             null);
535         controller.sendNotification(acn);
536         return true;
537     }
538
539     public static void restartAllPools() {
540         controller.reset();
541     }
542
543     /**
544     * Reload the config file (and apply changes to the pools loaded)
545     */

546     public Boolean JavaDoc refreshPoolConfigFile() {
547
548         // copy the current pools to an oldPools variable
549
ArrayList oldPools = new ArrayList();
550         for (int i = 0; i < pools.size(); i++) {
551             oldPools.add(pools.get(i));
552         }
553
554
555         // and reload frmo the config file
556
try {
557             loadPoolsFromConfigFile(false);
558         } catch (IOException ioe) {
559             ioe.printStackTrace(System.err);
560             return new Boolean JavaDoc("false");
561         }
562
563         if (oldPools.size() == pools.size()) {
564             // Now loop through the arrays, checking if anything is different
565
for (int i = 0; i < pools.size(); i++) {
566                 Properties pool = (Properties)pools.get(i);
567                 for (int j = 0; j < pools.size(); j++) {
568                     Properties oldPool = (Properties)oldPools.get(j);
569                     if (pool.getProperty("poolName").equals(oldPool.getProperty("poolName"))) {
570                         Set JavaDoc s = pool.entrySet();
571                         Set JavaDoc s1 = oldPool.entrySet();
572                         if (!s.equals(s1)) {
573                             // Get the pool queue and reset it (ie stop and start)
574
Queue q = getQueue(pool.getProperty("poolName"));
575                             ControllerLogger.log("[PoolController] Restarting " +pool.getProperty("poolName"));
576
577                             boolean queueConnectionRequests = true;
578                             if (pool.getProperty("queueConnectionRequests") != null) {
579                                 queueConnectionRequests = new Boolean JavaDoc(pool.getProperty("queueConnectionRequests")).booleanValue();
580                             }
581
582                             boolean runPooledMode = true;
583                             if (pool.getProperty("runPooledMode") != null) {
584                                 runPooledMode = new Boolean JavaDoc(pool.getProperty("runPooledMode")).booleanValue();
585                             }
586
587                             boolean connectionAutoCommit = true;
588                             if (pool.getProperty("connectionAutoCommit") != null) {
589                                 connectionAutoCommit = new Boolean JavaDoc(pool.getProperty("connectionAutoCommit")).booleanValue();
590                             }
591
592
593                             q.stopPool();
594                             q.restartPool(
595                                 pool.getProperty("poolName"),
596                                 new Integer JavaDoc(pool.getProperty("base")).intValue(),
597                                 new Integer JavaDoc(pool.getProperty("overflow")).intValue(),
598                                 pool.getProperty("log"),
599                                 new Integer JavaDoc(pool.getProperty("idleTime")),
600                                 new Boolean JavaDoc(pool.getProperty("messageLogging")),
601                                 new Boolean JavaDoc(pool.getProperty("sizeLogging")),
602                                 pool.getProperty("driverClass"),
603                                 pool.getProperty("driverURL"),
604                                 pool.getProperty("user"),
605                                 pool.getProperty("password"),
606                                 pool.getProperty("killActiveConnectionsOverAge"),
607                                 pool.getProperty("cycleConnections"),
608                                 queueConnectionRequests,
609                                 runPooledMode,
610                                 connectionAutoCommit,
611                                 pool.getProperty("connectionTransactionIsolation"),
612                                 pool.getProperty("checkSQL")
613                                 );
614                             break;
615                         }
616                     }
617                 }
618
619
620             }
621         // Right, they may have added more pools - so check for this
622
} else if (oldPools.size() < pools.size()) {
623             for (int i = 0; i < pools.size(); i++) {
624                 Properties pool = (Properties)pools.get(i);
625                 Queue q = getQueue(pool.getProperty("poolName"));
626                 if (q == null) {
627                     Boolean JavaDoc queueConnectionRequests = new Boolean JavaDoc("true");
628                     if (pool.getProperty("queueConnectionRequests") != null) {
629                         queueConnectionRequests = new Boolean JavaDoc(pool.getProperty("queueConnectionRequests"));
630                     }
631
632                     Boolean JavaDoc runPooledMode = new Boolean JavaDoc("true");
633                     if (pool.getProperty("runPooledMode") != null) {
634                         runPooledMode = new Boolean JavaDoc(pool.getProperty("runPooledMode"));
635                     }
636
637
638                     this.createNewPoolQueue(pool);
639                 }
640             }
641         // Or they've taken a pool out
642
} else {
643             for (int i = 0; i < oldPools.size(); i++) {
644                 Properties oldPool = (Properties)oldPools.get(i);
645                 String JavaDoc s = oldPool.getProperty("poolName");
646                 for (int j = 0; j < pools.size(); j++) {
647                     Properties pool = (Properties)pools.get(j);
648                     if (s.equals(pool.getProperty("poolName"))) {
649                         break;
650                     }
651                     if(j == pools.size()-1) {
652                         // Get the pool queue and unbind the JNDI contexts,
653
// stop the queue and deregister the MBean
654
Queue q = getQueue(s);
655                         q.stopPool();
656                         MBeanUtil.unRegisterSingle(_server, _mbeans, s);
657                         try {
658                             ctx = new InitialContext JavaDoc();
659                             ctx.unbind("q_" +s);
660                             ctx.unbind(s);
661                         } catch (javax.naming.NamingException JavaDoc ne) {
662                             ne.printStackTrace(System.err);
663                         }
664                     }
665
666                 }
667             }
668         }
669
670         return new Boolean JavaDoc("true");
671     }
672
673     public void loadPoolsFromConfigFile(String JavaDoc poolConfigFile, boolean actuallyLoad) throws IOException {
674         setPoolConfigFile(poolConfigFile);
675         loadPoolsFromConfigFile(actuallyLoad);
676     }
677
678     public void loadPoolsFromConfigFile(Properties pool) throws IOException {
679             if (pool.getProperty("poolName") == null) {
680                 CharArrayWriter caw = new CharArrayWriter();
681                 for (Enumeration e = pool.propertyNames() ; e.hasMoreElements() ;) {
682                     String JavaDoc key = (String JavaDoc)e.nextElement();
683                     caw.write(key +"=" +pool.getProperty(key) +"\n");
684                 }
685
686                 BufferedReader br = new BufferedReader(new StringReader(caw.toString()));
687                 setAdminDetails(br);
688             } else {
689                 this.createNewPoolQueue(pool);
690             }
691     }
692
693     public void loadPoolsFromConfigFile(boolean actuallyLoad) throws IOException {
694                 BufferedReader br = new BufferedReader(new FileReader(this.getPoolConfigFile()));
695                 loadPoolsFromConfigFile(br, actuallyLoad);
696     }
697
698     public void loadPoolsFromConfigFile(BufferedReader br, boolean actuallyLoad) throws IOException {
699         String JavaDoc line = "";
700         Properties pool = null;
701         if (pools != null) pools.clear();
702         while ((line = br.readLine()) != null) {
703             if (!line.trim().startsWith("#") && !line.trim().equals("")) {
704                 StringTokenizer st = new StringTokenizer(line, "=");
705                 int cnt = st.countTokens();
706                 String JavaDoc key = st.nextToken();
707                 String JavaDoc value = "";
708                 while (st.hasMoreTokens()) {
709                     value += (st.nextToken() +"=");
710                 }
711
712                 if (value.length() != 0) {
713                     value = value.substring(0, value.length() -1);
714                 }
715
716                 // don't load admin settings
717
if (key.startsWith("admin")) {
718                     continue;
719                 }
720
721                 if (key.equals("poolName")) {
722                     if (pool != null) {
723                         pools.add(pool);
724                         if (actuallyLoad) createNewPoolQueue(pool);
725                     }
726                     pool = new Properties();
727                 }
728
729                 pool.setProperty(key, value);
730             }
731         }
732
733         br.close();
734
735         pools.add(pool);
736
737         if (actuallyLoad) createNewPoolQueue(pool);
738
739
740     }
741
742
743     //////////////////////////////////////////////////////////////////////////////////////
744
/** Core methods (init, destroy, constructor)
745     //////////////////////////////////////////////////////////////////////////////////////
746
747     /**
748      * Method main. Allow commandline access.
749      * @param args
750      */

751     public static void main (String JavaDoc[] args) {
752         PoolController pc = new PoolController();
753         pc.init(args);
754     }
755
756
757     public PoolController() {
758         super();
759
760                 // Add a JVM shutdown hook to make sure the pool is shutdown on exit
761
PoolShutdownHook hook = new PoolShutdownHook(this);
762         Runtime.getRuntime().addShutdownHook(hook);
763
764     }
765
766     private void printInitMessage() {
767         ControllerLogger.log("");
768         ControllerLogger.log("---------------------------------");
769         ControllerLogger.log("[Primrose] initialising at " +new java.util.Date JavaDoc() +" ...");
770                 ControllerLogger.log("\tPrimrose version 2.7.3");// change the version before compiling !!!
771

772     }
773
774     private void createPoolControllerLog(String JavaDoc logFile) {
775         if (logFile == null) {
776             logFile = "./PoolController.log";
777             System.out.println("WARNING ! Primrose init : as of version 2.6.1, the PoolController.log location " +
778                             "is specified in the poolConfig.properties file, eg : " +
779                             "\n\tadminPoolControllerLogFile=/var/log/PoolController.log " +
780                             "\nThis has not been added, so am writing to the CWD (.) !");
781         }
782
783         // PoolController.log not specified - try to load it somehow else
784
// try to determine the tomcat home in DOS
785
// try to create the log file
786
try {
787             File f = new File(logFile);
788             if (!f.exists()) {
789                 f.createNewFile();
790             }
791
792             if (f.canWrite()) {
793                 ControllerLogger.setLogWriter(new PrintWriter(new FileOutputStream(f, true), true));
794             } else {
795                 System.err.println("[PoolController] Error initializing Primrose : Cannot write to log file : " +f.toString());
796             }
797
798         } catch (Exception JavaDoc e) {
799             e.printStackTrace(System.err);
800         }
801
802     }
803
804     /**
805     * Fire up the MBean, register with server
806     */

807     public void init(String JavaDoc[] args) {
808         controller = this;
809
810         _server = MBeanUtil.getMBeanServer(_server);
811         try {
812
813             // force them to load admin settings first
814
//if (this.getPoolConfigFile() != null) {
815
if (this.getPoolControllerLogFile() == null) {
816             System.out.println("\n\n-------------------------------------------\n" +
817                                 "[PoolController] WARNING !!!\n\tYou have not loaded a config with admin settings yet.\n" +
818                                 "\tAs of v2.6.1, this is not recommended, you must load a config file that contains \n"+
819                                 "\tthe PoolController log file location), eg :\n" +
820                                 "\t\t\tadminPoolControllerLogFile=/var/log/PoolController.log\n" +
821                                 "\tThis should be added in the \"admin\" section, not the pool instance section.\n" +
822                                 "\tIf you want to run the admin controller in silent mode (ie no logging), then set value to 'none'\n" +
823                                 "\tFor now, we'll continue loading, but with a default log (./PoolController.log) ... \n\tplease change this in the future !" +
824                                 "\n\n-------------------------------------------\n\n\n");
825
826                 setPoolControllerLogFile("./PoolController.log");
827             }
828
829             ObjectName objName = null;
830             // Load the description info for the mbean
831
setDescription();
832
833             objName = new ObjectName(PoolController.CONTROLLER_OBJECT_NAME);
834             ControllerLogger.log("\tOBJECT NAME = " + objName);
835             _server.registerMBean(controller, objName);
836             controller._mbeans.add(objName);
837
838             int port = Integer.parseInt(getAdminWebManagementPort());
839             // If they don't specify a port to have the admin page
840
// on then don't load it.
841

842             if (port != -1) {
843                 //String cssFileName = "C:/java/jakarta-tomcat-5.0.25/conf/primrose.css";
844
//String jsFileName = "C:/java/jakarta-tomcat-5.0.25/conf/primrose.js";
845
//HtmlJMXServer hjs = new HtmlJMXServer(++port, cssFileName, jsFileName);
846
//hjs.start();
847

848                 String JavaDoc adminPasswd = this.getAdminPassword();
849                 String JavaDoc encryptionKeyFile = null;
850                 if (args.length > 0) {
851                     encryptionKeyFile = args[0];
852                 }
853                 if (this.getPoolConfigFile() != null || encryptionKeyFile != null) {
854                     File f = null;
855
856                     if (this.getPoolConfigFile() != null) {
857                         File pcf = new File(this.getPoolConfigFile());
858                         String JavaDoc parentFileName = pcf.getParentFile().toString();
859                         if (parentFileName == null) {
860                             parentFileName = ".";
861                         }
862                         f = new File(parentFileName +File.separator +"pool.keys");
863                     } else {
864                         f = new File(encryptionKeyFile);
865                     }
866
867
868                     if (f.exists()) {
869                         if (adminPasswd.indexOf("__EQUALS__") != -1) {
870                             try {
871                                 ControllerLogger.log("[PoolController] Decrypting admin password '" +adminPasswd +"' from : " +f);
872                                 adminPasswd = new PoolCryptoTool().getDecryptedString(adminPasswd, f.toString());
873                                 this.adminPassword = adminPasswd;
874                             } catch (Exception JavaDoc e) {
875                                 e.printStackTrace(System.err);
876                                 ControllerLogger.log("[PoolController] ERROR : Cannot load PoolController because decryption of the password failed. See stderr for full stack trace");
877                                 return;
878                             }
879                         }
880
881                     } else {
882                         ControllerLogger.log("[PoolController] INFO : Not using password encryption for web management tool because cannot find file : " +f.toString());
883                     }
884                 }
885
886                 _html = MBeanUtil.createHTMLAdapter(_html, _server, _mbeans, this.getAdminUser(), adminPasswd, Integer.parseInt(getAdminWebManagementPort()));
887
888                 if (getAdminUser().equals("none") && adminPasswd.equals("none")) {
889                     ControllerLogger.log("[PoolController] Created web management tool on port(" +getAdminWebManagementPort() +"), with NO authentication (user and password are set to \"none\" in the poolConfig.properties file !");
890                 } else {
891                     ControllerLogger.log("[PoolController] Created web management tool on port(" +getAdminWebManagementPort() +"), user(" +getAdminUser() +"), password(" +getAdminPassword() +")");
892                 }
893             }
894
895         //ControllerLogger.log("[PoolController] Creating a JMXMP connector on port 1111 ...");
896
//JMXServiceURL url = new JMXServiceURL("jmxmp", null, 8091);
897
//JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, _server);
898

899         // Start the JMXMP connector server
900
//ControllerLogger.log("[PoolController] Start the JMXMP connector server...");
901
//cs.start();
902
//ControllerLogger.log("[PoolController] JMXMP connector server successfully started...");
903

904             // Add the notification listener
905
listener = new PoolControllerListener();
906                 ControllerLogger.log("[PoolController] Add notification listener to " +objName +"...");
907                 _server.addNotificationListener(objName, listener, null, null);
908
909             // Start the monitor object for the pool config file
910
if (this.getPoolConfigFile() != null) {
911                 File f = new File(this.getPoolConfigFile());
912                 lastModifiedMonitor = new ObjectMonitor();
913                 lastModifiedMonitor.setObservedObject(f);
914                 lastModifiedMonitor.setObservedMethod("lastModified", null);
915                 lastModifiedMonitor.setObservedMethodNotificationType(ObjectMonitor.DIFFERING);
916                 lastModifiedMonitor.setCheckValue(f.lastModified() +"");
917                 lastModifiedMonitor.setRefreshInterval(2000);
918                 //ObjectName monObjName = new ObjectName("Monitor:ObjectMonitor","attribute=File.lastModified",f.toString());
919
ObjectName monObjName = new ObjectName("Pool Monitor:name=ObjectMonitor(config file deployer)");
920                 _server.registerMBean(lastModifiedMonitor, monObjName);
921                 _server.addNotificationListener(monObjName, listener, null, null);
922                 //lastModifiedMonitor.start();
923
_mbeans.add(monObjName);
924             }
925
926             MBeanUtil.bind("pool", controller);
927
928             try {
929                 // NEED TO LOOK AT THIS !!!
930
// The class loader seems to be barfing on this but it might be
931
// due to security priviledeges ...
932
// Turns out its tomcat5 crappy version 1.1 of JMX
933
// No remote connector for now ...
934
//ControllerLogger.log("[PoolController] Binding remote JMX Connector ...");
935
//System.err.println("[PoolController] Binding remote JMX Connector ...");
936
//new RemoteClient().bindJMXConnector("localhost");
937
} catch (Exception JavaDoc e) {
938                 e.printStackTrace();
939             }
940
941             // instantiate an object which captures a 'quick glance'
942
// view of all the pools
943
allPoolOverviewBean = new AllPoolsOverview();
944             ObjectName monObjName = new ObjectName("Overview of All Pools:name=AllPoolsOverview");
945             _server.registerMBean(allPoolOverviewBean, monObjName);
946             _mbeans.add(monObjName);
947
948             //allPoolOverviewBean
949

950         } catch (Exception JavaDoc e) {
951             e.printStackTrace(System.err);
952             ControllerLogger.log("[PoolController] initialisation : ERROR: " + "Could not register the Controller MBean ... " +e);
953
954             return;
955         }
956
957     }
958
959     /**
960     * Shut down the pools, unbind the JNDI contexts and deregister the mbeans.
961     */

962
963     public void destroy() {
964         try {
965             ctx = new InitialContext JavaDoc();
966             for (int i = 0; i < _queues.size(); i++) {
967                 String JavaDoc n = ((Queue)_queues.get(i)).getName();
968
969                 if (ctx != null) {
970
971                     try { ctx.unbind(n); } catch (Exception JavaDoc e) {}
972                     try { ctx.unbind("q_" +n); } catch (Exception JavaDoc e) {}
973                 }
974                 ControllerLogger.log("[PoolController] Unbinding " +n +"...");
975                 ControllerLogger.log("[PoolController] Unbinding q_" +n +"...");
976
977             }
978             ControllerLogger.log("[PoolController] Stopping all pool queues ...");
979             controller.stopAllPoolQueues();
980             ControllerLogger.log("[PoolController] Stopping HTML monitor thread...");
981             if (_html != null) _html.stop();
982
983             ControllerLogger.log("[PoolController] Unregistering mbeans ...");
984             MBeanUtil.unRegisterAll(_server, _mbeans);
985
986             _mbeans.removeAll(_mbeans);
987             pools.removeAll(pools);
988             _queues.removeAll(_queues);
989
990             ControllerLogger.log("[PoolController] Shut down.");
991
992         } catch (Exception JavaDoc e) {
993             e.printStackTrace(System.err);
994         }
995
996
997
998     }
999
1000    //////////////////////////////////////////////////////////////////////////////////////
1001
/** Attribute methods **/
1002    //////////////////////////////////////////////////////////////////////////////////////
1003

1004    public void setPoolControllerLogFile(String JavaDoc poolControllerLogFile) {
1005        this.poolControllerLogFile = poolControllerLogFile;
1006        ControllerLogger.closeLogWriter();
1007        if (poolControllerLogFile.equals("none")) {
1008            // if the adminPoolControllerLogFile is "none" then set the log file
1009
// as null - this means they don't want any logging
1010
ControllerLogger.setLogWriter(null);
1011        } else {
1012            // set up the logger for the desired file
1013
createPoolControllerLog(poolControllerLogFile);
1014            printInitMessage();
1015        }
1016
1017    }
1018
1019    public String JavaDoc getPoolControllerLogFile() {
1020        return poolControllerLogFile;
1021    }
1022
1023    public void setPoolConfigFile(String JavaDoc poolConfigFile) {
1024        this.poolConfigFile = poolConfigFile;
1025    }
1026
1027    public String JavaDoc getPoolConfigFile() {
1028        return poolConfigFile;
1029    }
1030
1031    public String JavaDoc[] getEmail() {
1032        return email;
1033    }
1034
1035    public void setEmail(String JavaDoc[] email) {
1036        this.email = email;
1037    }
1038
1039    public void setAdminWebManagementPort(String JavaDoc adminWebManagementPort) {
1040        this.adminWebManagementPort = adminWebManagementPort;
1041    }
1042
1043    public String JavaDoc getAdminWebManagementPort() {
1044        return adminWebManagementPort;
1045    }
1046
1047    public boolean getEmailNotifications() {
1048        return emailNotifications;
1049    }
1050
1051    public void setEmailNotifications(boolean emailNotifications) {
1052        this.emailNotifications = emailNotifications;
1053
1054    }
1055
1056    public long getEmailNotificationPeriod() {
1057        return emailNotificationPeriod;
1058    }
1059
1060    public void setEmailNotificationPeriod(long emailNotificationPeriod) {
1061        this.emailNotificationPeriod = emailNotificationPeriod;
1062    }
1063
1064    public int getEmailMaxWarningNumber() {
1065        return emailMaxWarningNumber;
1066    }
1067
1068    public void setEmailMaxWarningNumber(int emailMaxWarningNumber) {
1069        this.emailMaxWarningNumber = emailMaxWarningNumber;
1070    }
1071
1072    public String JavaDoc getEmailSMTPServer() {
1073        return emailSMTPServer;
1074    }
1075
1076    public void setEmailSMTPServer(String JavaDoc emailSMTPServer) {
1077        this.emailSMTPServer = emailSMTPServer;
1078    }
1079
1080    public String JavaDoc getAdminUser() {
1081        return adminUser;
1082    }
1083
1084    public void setAdminUser(String JavaDoc adminUser) {
1085        this.adminUser = adminUser;
1086    }
1087
1088    public String JavaDoc getAdminPassword() {
1089        return adminPassword;
1090    }
1091
1092    public void setAdminPassword(String JavaDoc adminPassword) {
1093        this.adminPassword = adminPassword;
1094    }
1095
1096    public String JavaDoc getEmailCrisisAddress() {
1097        return adminEmailCrisisAddress;
1098    }
1099
1100    public void setEmailCrisisAddress(String JavaDoc adminEmailCrisisAddress) {
1101        this.adminEmailCrisisAddress = adminEmailCrisisAddress;
1102    }
1103
1104
1105    //////////////////////////////////////////////////////////////////////////////////////
1106
/** Helper methods **/
1107    //////////////////////////////////////////////////////////////////////////////////////
1108

1109    public void setAdminDetails(String JavaDoc fileName) throws IOException {
1110
1111        BufferedReader br = new BufferedReader(new FileReader(fileName));
1112        setAdminDetails(br);
1113    }
1114
1115    public void setAdminDetails(BufferedReader br) throws IOException {
1116        // build a workaround for people with earlier versions
1117
// that did not set the PoolController.log file location
1118
boolean havePoolControllerLogFileFlag = false;
1119        String JavaDoc line = "";
1120        while ((line = br.readLine()) != null) {
1121
1122            if (!line.trim().startsWith("#") && !line.trim().equals("")) {
1123                StringTokenizer st = new StringTokenizer(line, "=");
1124                int cnt = st.countTokens();
1125                String JavaDoc key = st.nextToken();
1126                String JavaDoc value = "";
1127                if (cnt >= 2) value = st.nextToken();
1128
1129                if (key.startsWith("admin")) {
1130                    if (key.equals("adminUser")) {
1131                        this.setAdminUser(value);
1132                    } else if (key.equals("adminPassword")) {
1133                        this.setAdminPassword(value);
1134                    } else if (key.equals("adminWebManagementPort")) {
1135                        this.setAdminWebManagementPort(value);
1136                    } else if (key.equals("adminEmailAddresses")) {
1137
1138                        StringTokenizer st1 = new StringTokenizer(value, ", ");
1139                        email = new String JavaDoc[st1.countTokens()];
1140                        int i = 0;
1141                        while (st1.hasMoreTokens()) {
1142                            email[i++] = st1.nextToken();
1143                        }
1144                        this.setEmail(email);
1145                    } else if (key.equals("adminEmailNotifcations") || key.equals("adminEmailNotifications")) {
1146                        this.setEmailNotifications(new Boolean JavaDoc(value).booleanValue());
1147                    } else if (key.equals("adminEmailSMTPServer")) {
1148                        this.setEmailSMTPServer(value);
1149                    } else if (key.equals("adminEmailNotificationPeriod")) {
1150                        if (value.length() != 0)
1151                        this.setEmailNotificationPeriod(Long.parseLong(value));
1152                    } else if (key.equals("adminEmailMaxWarningNumber")) {
1153                        if (value.length() != 0)
1154                        this.setEmailMaxWarningNumber(Integer.parseInt(value));
1155                    } else if (key.equals("adminEmailCrisisAddress")) {
1156                        this.setEmailCrisisAddress(value);
1157                    } else if (key.equals("adminPoolControllerLogFile")) {
1158                        this.setPoolControllerLogFile(value);
1159
1160                        havePoolControllerLogFileFlag = true;
1161                    } else {
1162                        ControllerLogger.log("[PoolController] unrecognised admin setting - ignoring line :" +line);
1163                    }
1164                }
1165            }
1166        }
1167
1168        // hack if no PoolController log file location is set
1169
if (!havePoolControllerLogFileFlag) {
1170            this.setPoolControllerLogFile(null);
1171        }
1172
1173        br.close();
1174    }
1175
1176    /**
1177    * A helper method for the DynamicMBean methods. Calls methods
1178    * dynamically with dynamic values.
1179    */

1180    private void callSetMethod(Attribute att) {
1181        Class JavaDoc targetClass = this.getClass();
1182        Method[] publicMethods = targetClass.getMethods();
1183        for (int j = 0; j < publicMethods.length; j++) {
1184            String JavaDoc fieldName = publicMethods[j].getName();
1185            Class JavaDoc typeClass = publicMethods[j].getReturnType();
1186            String JavaDoc fieldType = typeClass.getName();
1187            //System.err.println(" Name: " + fieldName +", Type: " + fieldType);
1188

1189            if (("set" +att.getName()).equalsIgnoreCase(fieldName)) {
1190                try {
1191                    publicMethods[j].invoke(this, new Object JavaDoc[]{att.getValue()});
1192                } catch (IllegalAccessException JavaDoc iae) {
1193                    iae.printStackTrace(System.err);
1194                } catch (InvocationTargetException ite) {
1195                    ite.printStackTrace(System.err);
1196                }
1197
1198            }
1199        }
1200    }
1201
1202    /**
1203    * A helper method for the DynamicMBean methods. Calls methods
1204    * dynamically with dynamic values.
1205    */

1206    private Object JavaDoc callGetMethod(String JavaDoc attributeName) {
1207        //System.err.println("callGetMethod " +attributeName);
1208
Class JavaDoc targetClass = this.getClass();
1209        Method[] publicMethods = targetClass.getMethods();
1210        for (int j = 0; j < publicMethods.length; j++) {
1211            String JavaDoc fieldName = publicMethods[j].getName();
1212            Class JavaDoc typeClass = publicMethods[j].getReturnType();
1213            String JavaDoc fieldType = typeClass.getName();
1214            //System.err.println(" Name: " + fieldName +", Type: " + fieldType);
1215

1216            if (("get" +attributeName).equalsIgnoreCase(fieldName)) {
1217                try {
1218                    //System.err.println("Found method, using " +fieldName);
1219
return publicMethods[j].invoke(this, null);
1220                } catch (IllegalAccessException JavaDoc iae) {
1221                    iae.printStackTrace(System.err);
1222                } catch (InvocationTargetException ite) {
1223                    ite.printStackTrace(System.err);
1224                }
1225
1226            }
1227        }
1228        return null;
1229    }
1230
1231    /**
1232    * Sets up the attribute, operation and constructor information for
1233    * rendering using the HTMLAdaptor server.
1234    */

1235    public void setDescription() {
1236            OpenMBeanOperationInfo[] operationInfo = new OpenMBeanOperationInfo[5];
1237
1238            operationInfo[0] = new OpenMBeanOperationInfoSupport(
1239                "stopAllPoolQueues", // name
1240
"Stop all queues, close all connections(and kill active connections). Contexts are NOT unbound.", // description
1241
// null,
1242
new OpenMBeanParameterInfo[]{}, // OpenMBeanParameterInfo[]
1243
SimpleType.VOID, // return type
1244
MBeanOperationInfo.ACTION // impact
1245
);
1246            operationInfo[1] = new OpenMBeanOperationInfoSupport(
1247                "reset", // name
1248
"This will stop all the pool queues, and then restart. In effect, cycles all live connections. \nSee stopAllPoolQueues() and startAllPoolQueues() description.", // description
1249
//null, // OpenMBeanParameterInfo[]
1250
new OpenMBeanParameterInfo[]{},
1251                SimpleType.VOID, // return type
1252
MBeanOperationInfo.ACTION // impact
1253
);
1254            OpenMBeanParameterInfo[] signature = new OpenMBeanParameterInfo[13];
1255            signature[0] = new OpenMBeanParameterInfoSupport(
1256                "poolName", // name
1257
"The JNDI pool name.", // description
1258
SimpleType.STRING
1259            );
1260            signature[1] = new OpenMBeanParameterInfoSupport(
1261                "base", // name
1262
"The number of base connections allowed.", // description
1263
SimpleType.INTEGER
1264            );
1265            signature[2] = new OpenMBeanParameterInfoSupport(
1266                "overflow", // name
1267
"The number of overflow connections allowed.", // description
1268
SimpleType.INTEGER
1269            );
1270            signature[3] = new OpenMBeanParameterInfoSupport(
1271                "log", // name
1272
"Pool Queue's log file.", // description
1273
SimpleType.STRING
1274            );
1275
1276            signature[4] = new OpenMBeanParameterInfoSupport(
1277                "idleTime", // name
1278
"The idle time for the (non-active) connections to timeout and be dumped.", // description
1279
SimpleType.INTEGER
1280            );
1281            signature[5] = new OpenMBeanParameterInfoSupport(
1282                "messageLogging", // name
1283
"Turn on/off pool message logging.", // description
1284
SimpleType.BOOLEAN
1285            );
1286            signature[6] = new OpenMBeanParameterInfoSupport(
1287                "sizeLogging", // name
1288
"Turn on/off pool size logging", // description
1289
SimpleType.BOOLEAN
1290            );
1291            signature[7] = new OpenMBeanParameterInfoSupport(
1292                "driverClass", // name
1293
"Database driver class.", // description
1294
SimpleType.STRING
1295            );
1296            signature[8] = new OpenMBeanParameterInfoSupport(
1297                "driverURL", // name
1298
"Database connection URL.", // description
1299
SimpleType.STRING
1300            );
1301
1302            signature[9] = new OpenMBeanParameterInfoSupport(
1303                "user", // name
1304
"Database schema user.", // description
1305
SimpleType.STRING
1306            );
1307            signature[10] = new OpenMBeanParameterInfoSupport(
1308                "password", // name
1309
"Database schema password.", // description
1310
SimpleType.STRING
1311            );
1312
1313            signature[11] = new OpenMBeanParameterInfoSupport(
1314                "killActiveConnectionsOverAge", // name
1315
"Kill Active Connections Over Age (milliseconds).", // description
1316
SimpleType.STRING
1317            );
1318
1319            signature[12] = new OpenMBeanParameterInfoSupport(
1320                "cycleConnections", // name
1321
"After n number of SQL transactions for a connection, cycle it", // description
1322
SimpleType.STRING
1323            );
1324
1325            operationInfo[2] = new OpenMBeanOperationInfoSupport(
1326                "createNewPoolQueue", // name
1327
"Start a new pool.", // description
1328
signature, // OpenMBeanParameterInfo[]
1329
SimpleType.STRING, // return type
1330
MBeanOperationInfo.ACTION // impact
1331
);
1332
1333            operationInfo[3] = new OpenMBeanOperationInfoSupport(
1334                "refreshPoolConfigFile", // name
1335
"Refresh the pool config file data (ie reload pools if data changed).", // description
1336
// null, // OpenMBeanParameterInfo[]
1337
new OpenMBeanParameterInfo[]{},
1338                SimpleType.BOOLEAN, // return type
1339
MBeanOperationInfo.ACTION // impact
1340
);
1341
1342            operationInfo[4] = new OpenMBeanOperationInfoSupport(
1343                "startAllPoolQueues", // name
1344
"Start all queues, usually used after a stopAllPoolQueues() operation.", // description
1345
// null, // OpenMBeanParameterInfo[]
1346
new OpenMBeanParameterInfo[]{},
1347                SimpleType.VOID, // return type
1348
MBeanOperationInfo.ACTION // impact
1349
);
1350
1351            OpenMBeanAttributeInfo[] attributeInfo = new OpenMBeanAttributeInfo[10];
1352            try {
1353                attributeInfo[0] = new OpenMBeanAttributeInfoSupport(
1354                    "email",
1355                    "Email notification addresses for pool events.",
1356                    new ArrayType(1, SimpleType.STRING),
1357                    true,
1358                    true,
1359                    false
1360                );
1361
1362                attributeInfo[1] = new OpenMBeanAttributeInfoSupport(
1363                    "poolConfigFile",
1364                    "The configuration file for the pool.",
1365                    SimpleType.STRING,
1366                    true,
1367                    true, // writable
1368
false
1369                );
1370
1371                attributeInfo[2] = new OpenMBeanAttributeInfoSupport(
1372                    "emailNotifications",
1373                    "Whether or not email notifications for pool events should be enabled (events are the pools starting or stopping, and pool crisis information).",
1374                    SimpleType.BOOLEAN,
1375                    true,
1376                    true,
1377                    false
1378                );
1379
1380                attributeInfo[3] = new OpenMBeanAttributeInfoSupport(
1381                    "adminWebManagementPort",
1382                    "The port that this tool can be accessed from (set in the poolConfig.properties file).",
1383                    SimpleType.STRING,
1384                    true,
1385                    false,
1386                    false
1387                );
1388
1389                attributeInfo[4] = new OpenMBeanAttributeInfoSupport(
1390                    "adminUser",
1391                    "The user name for the admin user (set in the poolConfig.properties file).",
1392                    SimpleType.STRING,
1393                    true,
1394                    false,
1395                    false
1396                );
1397
1398                attributeInfo[5] = new OpenMBeanAttributeInfoSupport(
1399                    "adminPassword",
1400                    "The password for the admin user (set in the poolConfig.properties file).",
1401                    SimpleType.STRING,
1402                    true,
1403                    false,
1404                    false
1405                );
1406
1407                attributeInfo[6] = new OpenMBeanAttributeInfoSupport(
1408                    "emailSMTPServer",
1409                    "The SMTP server to use to send email warnings (if email notification is 'true').",
1410                    SimpleType.STRING,
1411                    true,
1412                    false,
1413                    false
1414                );
1415
1416                attributeInfo[7] = new OpenMBeanAttributeInfoSupport(
1417                    "emailNotificationPeriod",
1418                    "If there are problems with the pool, and until the problem is fixed, how often should the pool mail you about the problem.",
1419                    SimpleType.LONG,
1420                    true,
1421                    true,
1422                    false
1423                );
1424
1425                attributeInfo[8] = new OpenMBeanAttributeInfoSupport(
1426                    "emailMaxWarningNumber",
1427                    "If there are problems with the pool, and until the problem is fixed, what is the maximum number of email warnings to send ?.",
1428                    SimpleType.INTEGER,
1429                    true,
1430                    true,
1431                    false
1432                );
1433                attributeInfo[9] = new OpenMBeanAttributeInfoSupport(
1434                    "adminEmailCrisisAddress",
1435                    "Crisis email address. If email notificatiosn are on, and the max number of emails to thte normal address have been sent, this email address will be used to send a final crisis alert.",
1436                    SimpleType.STRING,
1437                    true,
1438                    true,
1439                    false
1440                );
1441
1442
1443            } catch (OpenDataException ode) {
1444                ode.printStackTrace(System.err);
1445            }
1446
1447            _MBeanInfo = new OpenMBeanInfoSupport(
1448                this.getClass().getName(), // DynamicMBean implementing class name
1449
"PoolController.<br>This class contols the starting and stopping of pools.<br>Think before you use !", // description
1450
attributeInfo, // MBeanAttributeInfo[]
1451
// null, // MBeanConstructorInfo[]
1452
new OpenMBeanConstructorInfo[]{},
1453                operationInfo, // MBeanOperationInfo[]
1454
// null // MBeanNotificationInfo[]
1455
new MBeanNotificationInfo[]{}
1456            );
1457    }
1458
1459    //////////////////////////////////////////////////////////////////////////////////////
1460
/** DynamicMBean implementation methods **/
1461    //////////////////////////////////////////////////////////////////////////////////////
1462

1463    public MBeanInfo getMBeanInfo () {
1464        //System.err.println("getMBeanInfo " +_MBeanInfo);
1465
return (_MBeanInfo);
1466    }
1467
1468
1469    /**
1470    * Obtains the value of a specific attribute of the Dynamic MBean.
1471    *
1472    * @param attribute The name of the attribute to be retrieved
1473    *
1474    * @return The value of the attribute retrieved.
1475    *
1476    * @exception AttributeNotFoundException
1477    * @exception MBeanException Wraps a <CODE>java.lang.Exception</CODE> thrown by the MBean's getter.
1478    * @exception ReflectionException Wraps a <CODE>java.lang.Exception</CODE> thrown while trying to invoke the getter.
1479    */

1480    public Object JavaDoc getAttribute (String JavaDoc attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException {
1481        //System.err.println("getAttribute");
1482
return callGetMethod(attributeName);
1483    }
1484
1485    /**
1486    * Sets the value of a specific attribute of the Dynamic MBean
1487    *
1488    * @param attribute The identification of the attribute to
1489    * be set and the value it is to be set to.
1490    *
1491    * @exception AttributeNotFoundException
1492    * @exception InvalidAttributeValueException
1493    * @exception MBeanException Wraps a <CODE>java.lang.Exception</CODE> thrown by the MBean's setter.
1494    * @exception ReflectionException Wraps a <CODE>java.lang.Exception</CODE> thrown while trying to invoke the MBean's setter.
1495    */

1496    public void setAttribute (Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
1497        //System.err.println("setAttribute");
1498
callSetMethod(attribute);
1499
1500    }
1501    /**
1502    * Enables the values of several attributes of the Dynamic MBean.
1503    *
1504    * @param attributes A list of the attributes to be retrieved.
1505    *
1506    * @return The list of attributes retrieved.
1507    *
1508    */

1509    public AttributeList getAttributes (String JavaDoc[] attributeNames) {
1510        //System.err.println("getAttributes");
1511
AttributeList resultList = new AttributeList();
1512        for (int aa = 0; aa < attributeNames.length; aa++) {
1513            try {
1514                Object JavaDoc value = getAttribute((String JavaDoc)attributeNames[aa]);
1515                resultList.add(new Attribute(attributeNames[aa], value));
1516            } catch (Exception JavaDoc e) {
1517                e.printStackTrace();
1518            }
1519        }
1520        return resultList;
1521    }
1522    /**
1523    * Sets the values of several attributes of the Dynamic MBean
1524    *
1525    * @param name The object name of the MBean within which the attributes are to
1526    * be set.
1527    * @param attributes A list of attributes: The identification of the
1528    * attributes to be set and the values they are to be set to.
1529    *
1530    * @return The list of attributes that were set, with their new values.
1531    *
1532    */

1533    public AttributeList setAttributes (AttributeList attributes) {
1534        //System.err.println("setAttributes");
1535
for (int i = 0; i < attributes.size(); i++) {
1536            Attribute att = (Attribute)attributes.get(i);
1537            callSetMethod(att);
1538
1539        }
1540        return attributes;
1541    }
1542
1543    /**
1544    * Allows an action to be invoked on the Dynamic MBean.
1545    *
1546    * @param actionName The name of the action to be invoked.
1547    * @param params An array containing the parameters to be set when the action is
1548    * invoked.
1549    * @param signature An array containing the signature of the action. The class objects will
1550    * be loaded through the same class loader as the one used for loading the
1551    * MBean on which the action is invoked.
1552    *
1553    * @return The object returned by the action, which represents the result of
1554    * invoking the action on the MBean specified.
1555    *
1556    * @exception MBeanException Wraps a <CODE>java.lang.Exception</CODE> thrown by the MBean's invoked method.
1557    * @exception ReflectionException Wraps a <CODEjava.lang.Exception</CODE thrown while trying to invoke the method
1558    */

1559    public Object JavaDoc invoke (String JavaDoc operationName, Object JavaDoc params[], String JavaDoc signature[]) throws MBeanException, ReflectionException {
1560        Object JavaDoc ret = Void.TYPE;
1561        //System.err.println("invoke " +operationName);
1562
//
1563
// Turn the signature into a Class array so we can get the Method
1564
/// object and invoke the method, passing params
1565
//
1566
try {
1567            Class JavaDoc[] sign = null;
1568            if (params != null) {
1569                sign = new Class JavaDoc[signature.length];
1570                for (int aa = 0; aa < signature.length; aa++) {
1571                    try {
1572                        sign[aa] = MBeanUtil.getClassFromString(signature[aa]);
1573                    } catch (ClassNotFoundException JavaDoc e) {
1574                        throw new RuntimeOperationsException(new IllegalArgumentException JavaDoc(
1575                                "PoolController.invoke(): ERROR: " + "Bad argument \'"
1576                                + sign[aa] + " found when attempting to invoke operation \'"
1577                                + operationName + "\'!"));
1578                    }
1579                }
1580            }
1581
1582            Method theMethod = this.getClass().getMethod(operationName, sign);
1583            ret = theMethod.invoke(this, params);
1584
1585        } catch (NoSuchMethodException JavaDoc e) {
1586            throw new ReflectionException(e, e.getClass().getName());
1587        } catch (IllegalAccessException JavaDoc e) {
1588            throw new ReflectionException(e, e.getClass().getName());
1589        } catch (InvocationTargetException e) {
1590            throw new ReflectionException(e, e.getClass().getName());
1591        }
1592        return ret;
1593    }
1594
1595}
1596
Popular Tags