KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > cjdbc > console > jmx > RmiJmxClient


1 /**
2  * C-JDBC: Clustered JDBC.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: c-jdbc@objectweb.org
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation; either version 2.1 of the License, or any later
10  * version.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * Initial developer(s): Nicolas Modrzyk
22  * Contributor(s): ______________________.
23  */

24
25 package org.objectweb.cjdbc.console.jmx;
26
27 import java.io.IOException JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Set JavaDoc;
32
33 import javax.management.Attribute JavaDoc;
34 import javax.management.InstanceNotFoundException JavaDoc;
35 import javax.management.MBeanInfo JavaDoc;
36 import javax.management.MBeanOperationInfo JavaDoc;
37 import javax.management.MBeanParameterInfo JavaDoc;
38 import javax.management.MBeanServerConnection JavaDoc;
39 import javax.management.MBeanServerInvocationHandler JavaDoc;
40 import javax.management.NotificationListener JavaDoc;
41 import javax.management.ObjectName JavaDoc;
42 import javax.management.monitor.StringMonitor JavaDoc;
43 import javax.management.remote.JMXConnector JavaDoc;
44 import javax.management.remote.JMXConnectorFactory JavaDoc;
45 import javax.management.remote.JMXServiceURL JavaDoc;
46 import javax.naming.Context JavaDoc;
47 import javax.security.auth.Subject JavaDoc;
48
49 import org.objectweb.cjdbc.common.exceptions.VirtualDatabaseException;
50 import org.objectweb.cjdbc.common.jmx.JmxConstants;
51 import org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean;
52 import org.objectweb.cjdbc.common.jmx.mbeans.DataCollectorMBean;
53 import org.objectweb.cjdbc.common.jmx.mbeans.DatabaseBackendMBean;
54 import org.objectweb.cjdbc.common.jmx.mbeans.VirtualDatabaseMBean;
55 import org.objectweb.cjdbc.common.users.AdminUser;
56 import org.objectweb.cjdbc.controller.authentication.PasswordAuthenticator;
57
58 /**
59  * This class defines a RmiJmxClient that uses Jmx 2.0 specifications to connect
60  * to the RmiSever
61  *
62  * @author <a HREF="mailto:Nicolas.Modrzyk@inria.fr">Nicolas Modrzyk </a>
63  * @version 1.0
64  */

65 public class RmiJmxClient
66 {
67   private JMXConnector JavaDoc connector;
68   private Object JavaDoc credentials;
69   private String JavaDoc remoteHostAddress;
70   private String JavaDoc remoteHostPort;
71
72   private NotificationListener JavaDoc notificationListener;
73
74   // List of last used MBeans
75
private ControllerMBean controllerMBean;
76   private VirtualDatabaseMBean virtualDbMBean;
77   private DatabaseBackendMBean backendMBean;
78   private DataCollectorMBean dataMBean;
79
80   /**
81    * Returns the notificationListener value.
82    *
83    * @return Returns the notificationListener.
84    */

85   public NotificationListener JavaDoc getNotificationListener()
86   {
87     return notificationListener;
88   }
89
90   /**
91    * Sets the notificationListener value.
92    *
93    * @param notificationListener The notificationListener to set.
94    */

95   public void setNotificationListener(NotificationListener JavaDoc notificationListener)
96   {
97     this.notificationListener = notificationListener;
98   }
99
100   /**
101    * Returns the credentials value.
102    *
103    * @return Returns the credentials.
104    */

105   public Object JavaDoc getCredentials()
106   {
107     return credentials;
108   }
109
110   /**
111    * Creates a new <code>RmiJmxClient.java</code> object
112    *
113    * @param port the port of the host to connect to
114    * @param host the host name to connect to
115    * @param jmxUser the jmxUser if one, to be authenticated with
116    * @param jmxPassword the jmxPassword if one, to be authenticated with
117    * @throws IOException if cannot connect
118    */

119   public RmiJmxClient(String JavaDoc port, String JavaDoc host, String JavaDoc jmxUser,
120       String JavaDoc jmxPassword) throws IOException JavaDoc
121   {
122     this(port, host, PasswordAuthenticator.createCredentials(jmxUser,
123         jmxPassword));
124   }
125
126   /**
127    * Creates a new <code>RmiJmxClient</code> object
128    *
129    * @param url the jmx connector url
130    * @param credentials to use for the connection
131    * @throws IOException if connect fails
132    */

133   public RmiJmxClient(String JavaDoc url, Object JavaDoc credentials) throws IOException JavaDoc
134   {
135     int index = url.indexOf(":");
136     String JavaDoc ip = url.substring(0, index);
137     String JavaDoc port = url.substring(index + 1);
138     connect(port, ip, credentials);
139   }
140
141   /**
142    * Creates a new <code>RmiJmxClient.java</code> object
143    *
144    * @param port the port of the host to connect to
145    * @param host the host name to connect to
146    * @param credentials to use for the connection
147    * @throws IOException if connect fails
148    */

149   public RmiJmxClient(String JavaDoc port, String JavaDoc host, Object JavaDoc credentials)
150       throws IOException JavaDoc
151   {
152     connect(port, host, credentials);
153   }
154
155   /**
156    * Connect to the MBean server
157    *
158    * @param port the port of the host to connect to
159    * @param host the host name to connect to
160    * @param credentials to use for the connection
161    * @throws IOException if connect fails
162    */

163   public void connect(String JavaDoc port, String JavaDoc host, Object JavaDoc credentials)
164       throws IOException JavaDoc
165   {
166     JMXServiceURL JavaDoc address = new JMXServiceURL JavaDoc("rmi", host, 0, "/jndi/jrmp");
167
168     Map JavaDoc environment = new HashMap JavaDoc();
169     environment.put(Context.INITIAL_CONTEXT_FACTORY,
170         "com.sun.jndi.rmi.registry.RegistryContextFactory");
171     environment.put(Context.PROVIDER_URL, "rmi://" + host + ":" + port);
172
173     // use username and password for authentication of connections
174
// with the controller, the values are compared to the ones
175
// specified in the controller.xml config file.
176
if (credentials != null)
177     {
178       // this line is not required if no username/password has been configered
179
environment.put(JMXConnector.CREDENTIALS, credentials);
180     }
181
182     this.credentials = credentials;
183
184     connector = JMXConnectorFactory.connect(address, environment);
185     remoteHostAddress = host;
186     remoteHostPort = port;
187     invalidateMBeans();
188   }
189
190   /**
191    * Invalidate all MBeans.
192    *
193    * When connecting to a new Controller, all the local
194    * MBean instances must be invalidated (since they
195    * refered to the previous Controller and its associated
196    * MBean server).
197    */

198   private void invalidateMBeans()
199   {
200     controllerMBean = null;
201     virtualDbMBean = null;
202     dataMBean = null;
203     backendMBean = null;
204   }
205
206   /**
207    * List of all the mbean on the current server
208    *
209    * @return a set of <tt>ObjectInstance</tt>
210    * @throws Exception if fails
211    */

212   public Set JavaDoc listCJDBCMBeans() throws Exception JavaDoc
213   {
214     Set JavaDoc set = connector.getMBeanServerConnection().queryMBeans(
215         new ObjectName JavaDoc("c-jdbc:*"), null);
216     return set;
217   }
218
219   /**
220    * Get the mbean information
221    *
222    * @param mbean the <tt>ObjectName</tt> of the mbean to access
223    * @return <tt>MBeanInfo</tt> object
224    * @throws Exception if fails
225    */

226   public MBeanInfo JavaDoc getMBeanInfo(ObjectName JavaDoc mbean) throws Exception JavaDoc
227   {
228     return connector.getMBeanServerConnection().getMBeanInfo(mbean);
229   }
230
231   /**
232    * Get the value of an attribute on the given mbean
233    *
234    * @param mbean the <tt>ObjectName</tt> of the mbean to access
235    * @param attribute the attribute name
236    * @return <tt>Object</tt> being the value returned by the get <Attribute>
237    * method
238    * @throws Exception if fails
239    */

240   public Object JavaDoc getAttributeValue(ObjectName JavaDoc mbean, String JavaDoc attribute)
241       throws Exception JavaDoc
242   {
243     return connector.getMBeanServerConnection().getAttribute(mbean, attribute);
244   }
245
246   /**
247    * Change an attribute value
248    *
249    * @param mbean the <tt>ObjectName</tt> of the mbean to access
250    * @param attribute the attribute name
251    * @param value the attribute new value
252    * @throws Exception if fails
253    */

254   public void setAttributeValue(ObjectName JavaDoc mbean, String JavaDoc attribute, Object JavaDoc value)
255       throws Exception JavaDoc
256   {
257     Attribute JavaDoc att = new Attribute JavaDoc(attribute, value);
258     connector.getMBeanServerConnection().setAttribute(mbean, att);
259   }
260
261   /**
262    * Set the current subject for authentication
263    *
264    * @param user the user login
265    * @param password the user password
266    */

267   public void setCurrentSubject(String JavaDoc user, String JavaDoc password)
268   {
269     if (user != null && password != null)
270     {
271       // we build a subject for authentication
272
AdminUser dbUser = new AdminUser(user, password);
273       Set JavaDoc principals = new HashSet JavaDoc();
274       principals.add(dbUser);
275       subject = new Subject JavaDoc(true, principals, new HashSet JavaDoc(), new HashSet JavaDoc());
276     }
277   }
278
279   Subject JavaDoc subject;
280
281   /**
282    * Has the subject been set?
283    *
284    * @return true if the subject is not null
285    */

286   public boolean isSubjectSet()
287   {
288     return subject != null;
289   }
290
291   /**
292    * Invoke an operation on the given object.
293    *
294    * @param name object name
295    * @param operation operation to invoke
296    * @param args method arguments
297    * @return result of operation invocation
298    * @throws Exception if an error occurs
299    */

300   public Object JavaDoc invokeOperation(ObjectName JavaDoc name, MBeanOperationInfo JavaDoc operation,
301       Object JavaDoc[] args) throws Exception JavaDoc
302   {
303     if (JmxConstants.mbeanNeedAuthentication(name))
304     {
305       if (!isSubjectSet())
306         throw new Exception JavaDoc(
307             "Subject has not been set for this jmx client, and authentication is required");
308       return connector.getMBeanServerConnection(subject).invoke(name,
309           operation.getName(), args, getSignature(operation));
310     }
311     else
312     {
313       return connector.getMBeanServerConnection().invoke(name,
314           operation.getName(), args, getSignature(operation));
315     }
316   }
317
318   private String JavaDoc[] getSignature(MBeanOperationInfo JavaDoc operation)
319   {
320     MBeanParameterInfo JavaDoc[] info = operation.getSignature();
321     String JavaDoc[] signature = new String JavaDoc[info.length];
322     for (int i = 0; i < info.length; i++)
323       signature[i] = info[i].getType();
324     return signature;
325   }
326
327   /**
328    * Get a reference to the virtualdatabaseMbean with the given authentication
329    *
330    * @param database the virtual database name
331    * @param user the user recognized as the <code>VirtualDatabaseUser</code>
332    * @param password the password for the <code>VirtualDatabaseUser</code>
333    * @return <code>VirtualDatabaseMBean</code> instance
334    * @throws IOException if cannot connect to MBean
335    * @throws InstanceNotFoundException if cannot locate MBean
336    * @throws VirtualDatabaseException if virtual database fails
337    */

338   public VirtualDatabaseMBean getVirtualDatabaseProxy(String JavaDoc database,
339       String JavaDoc user, String JavaDoc password) throws InstanceNotFoundException JavaDoc,
340       IOException JavaDoc, VirtualDatabaseException
341   {
342     if (virtualDbMBean != null && isValidConnection()
343         && virtualDbMBean.getVirtualDatabaseName().equals(database))
344     {
345       return virtualDbMBean;
346     }
347     else
348     {
349       ObjectName JavaDoc db = JmxConstants.getVirtualDbObjectName(database);
350
351       // we build a subject for authentication
352
AdminUser dbUser = new AdminUser(user, password);
353       Set JavaDoc principals = new HashSet JavaDoc();
354       principals.add(dbUser);
355       Subject JavaDoc subj = new Subject JavaDoc(true, principals, new HashSet JavaDoc(), new HashSet JavaDoc());
356
357       // we open a connection for this subject, all subsequent calls with this
358
// connection will be executed on the behalf of our subject.
359
MBeanServerConnection JavaDoc delegateConnection = connector
360           .getMBeanServerConnection(subj);
361
362       // we create a proxy to the virtual database
363
VirtualDatabaseMBean local = (VirtualDatabaseMBean) MBeanServerInvocationHandler
364           .newProxyInstance(delegateConnection, db, VirtualDatabaseMBean.class,
365               false);
366
367       // Check authentication
368
boolean authenticated = false;
369       try
370       {
371         authenticated = local.checkAdminAuthentication(user, password);
372       }
373       catch (Exception JavaDoc e)
374       {
375         throw new VirtualDatabaseException(
376             "Could not check authentication. MBean is not accessible.");
377       }
378       if (!authenticated)
379         throw new VirtualDatabaseException("Authentication Failed");
380
381       // Add notification listener
382
if (notificationListener != null)
383       {
384         delegateConnection.addNotificationListener(db, notificationListener,
385             null, null);
386
387         // CounterMonitor cm = new CounterMonitor();
388
// cm.setNotify(true);
389
// cm.setGranularityPeriod(100);
390
// cm.setObservedObject(db);
391
// cm.setObservedAttribute("currentNbOfThreads");
392
// cm.setThreshold(new Integer(6));
393
// cm.start();
394
}
395
396       this.virtualDbMBean = local;
397
398       return virtualDbMBean;
399     }
400   }
401
402   /**
403    * Get a proxy to the ControllerMBean
404    *
405    * @return <code>ControllerMBean</code> instance
406    * @throws IOException if cannot connect to MBean
407    */

408   public ControllerMBean getControllerProxy() throws IOException JavaDoc
409   {
410
411     if (controllerMBean != null && isValidConnection())
412     {
413       return controllerMBean;
414     }
415     else
416     {
417       if (!isValidConnection())
418         reconnect();
419
420       ObjectName JavaDoc db = JmxConstants.getControllerObjectName();
421
422       // we create a new proxy to the controller
423
controllerMBean = (ControllerMBean) MBeanServerInvocationHandler
424           .newProxyInstance(connector.getMBeanServerConnection(), db,
425               ControllerMBean.class, false);
426
427       // Add notification listener
428
if (notificationListener != null)
429       {
430         try
431         {
432           connector.getMBeanServerConnection().addNotificationListener(db,
433               notificationListener, null, null);
434         }
435         catch (Exception JavaDoc e)
436         {
437           throw new IOException JavaDoc("Could not register listener on the mbean");
438         }
439       }
440
441       return controllerMBean;
442     }
443   }
444
445   /**
446    * Get a proxy to the DataCollectorMBean
447    *
448    * @return <code>DataCollectorMBean</code> instance
449    * @throws IOException if fails
450    */

451   public DataCollectorMBean getDataCollectorProxy() throws IOException JavaDoc
452   {
453
454     if (dataMBean != null && isValidConnection())
455     {
456       return dataMBean;
457     }
458     else
459     {
460       if (!isValidConnection())
461         reconnect();
462       ObjectName JavaDoc db = JmxConstants.getDataCollectorObjectName();
463
464       // we create a new proxy to the data collector
465
dataMBean = (DataCollectorMBean) MBeanServerInvocationHandler
466           .newProxyInstance(connector.getMBeanServerConnection(), db,
467               DataCollectorMBean.class, false);
468       return dataMBean;
469     }
470   }
471
472   /**
473    * Get a proxy to the DatabaseBackendMBean
474    *
475    * @return <code>DatabaseBackendMBean</code> instance
476    * @param vdb virtual database name
477    * @param backend backend name
478    * @param user user name
479    * @param password password name
480    * @throws IOException if cannot connect to MBean
481    * @throws InstanceNotFoundException if cannot locate MBean
482    */

483   public DatabaseBackendMBean getDatabaseBackendProxy(String JavaDoc vdb,
484       String JavaDoc backend, String JavaDoc user, String JavaDoc password)
485       throws InstanceNotFoundException JavaDoc, IOException JavaDoc
486   {
487     if (backendMBean != null && isValidConnection())
488     {
489       try
490       {
491         if (backendMBean.getName().equals(backend))
492           return backendMBean;
493       }
494       catch (Exception JavaDoc e)
495       {
496         // backend is no more there
497
}
498     }
499
500     if (!isValidConnection())
501       reconnect();
502
503     // we build a subject for authentication
504
AdminUser dbUser = new AdminUser(user, password);
505     Set JavaDoc principals = new HashSet JavaDoc();
506     principals.add(dbUser);
507     Subject JavaDoc subj = new Subject JavaDoc(true, principals, new HashSet JavaDoc(), new HashSet JavaDoc());
508
509     ObjectName JavaDoc db = JmxConstants.getDatabaseBackendObjectName(vdb, backend);
510     MBeanServerConnection JavaDoc delegateConnection = connector
511         .getMBeanServerConnection(subj);
512
513     if (notificationListener != null)
514     {
515       delegateConnection.addNotificationListener(db, notificationListener,
516           null, null);
517       StringMonitor JavaDoc sm = new StringMonitor JavaDoc();
518       sm.setObservedObject(db);
519       sm.setObservedAttribute("LastKnownCheckpoint");
520       sm.setStringToCompare("hello");
521       sm.setGranularityPeriod(100);
522       sm.setNotifyDiffer(true);
523       sm.addNotificationListener(notificationListener, null, null);
524       sm.start();
525     }
526
527     // we create a proxy to the database backend
528
backendMBean = (DatabaseBackendMBean) MBeanServerInvocationHandler
529         .newProxyInstance(delegateConnection, db, DatabaseBackendMBean.class,
530             false);
531     return backendMBean;
532   }
533
534   /**
535    * Get the controller name used for jmx connection This is
536    * [hostname]:[jmxServerPort]
537    *
538    * @return <code>remoteHostName+":"+remoteHostPort</code>
539    */

540   public String JavaDoc getRemoteName()
541   {
542     return remoteHostAddress + ":" + remoteHostPort;
543   }
544
545   /**
546    * Returns the remoteHostAddress value.
547    *
548    * @return Returns the remoteHostAddress.
549    */

550   public String JavaDoc getRemoteHostAddress()
551   {
552     return remoteHostAddress;
553   }
554
555   /**
556    * Returns the remoteHostPort value.
557    *
558    * @return Returns the remoteHostPort.
559    */

560   public String JavaDoc getRemoteHostPort()
561   {
562     return remoteHostPort;
563   }
564
565   /**
566    * Reconnect to the same mbean server
567    *
568    * @throws IOException if reconnection failed
569    */

570   public void reconnect() throws IOException JavaDoc
571   {
572     connect(remoteHostPort, remoteHostAddress, credentials);
573   }
574
575   /**
576    * Test if the connection with the mbean server is still valid
577    *
578    * @return true if it is
579    */

580   public boolean isValidConnection()
581   {
582     try
583     {
584       connector.getMBeanServerConnection().getMBeanCount();
585       return true;
586     }
587     catch (Exception JavaDoc e)
588     {
589       controllerMBean = null;
590       backendMBean = null;
591       virtualDbMBean = null;
592       dataMBean = null;
593       return false;
594     }
595   }
596 }
Popular Tags