00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 package org.objectweb.cjdbc.console.jmx;
00026
00027 import java.io.IOException;
00028 import java.util.HashMap;
00029 import java.util.HashSet;
00030 import java.util.Map;
00031 import java.util.Set;
00032
00033 import javax.management.Attribute;
00034 import javax.management.InstanceNotFoundException;
00035 import javax.management.MBeanInfo;
00036 import javax.management.MBeanOperationInfo;
00037 import javax.management.MBeanParameterInfo;
00038 import javax.management.MBeanServerConnection;
00039 import javax.management.MBeanServerInvocationHandler;
00040 import javax.management.NotificationListener;
00041 import javax.management.ObjectName;
00042 import javax.management.monitor.StringMonitor;
00043 import javax.management.remote.JMXConnector;
00044 import javax.management.remote.JMXConnectorFactory;
00045 import javax.management.remote.JMXServiceURL;
00046 import javax.naming.Context;
00047 import javax.security.auth.Subject;
00048
00049 import org.objectweb.cjdbc.common.exceptions.VirtualDatabaseException;
00050 import org.objectweb.cjdbc.common.jmx.JmxConstants;
00051 import org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean;
00052 import org.objectweb.cjdbc.common.jmx.mbeans.DataCollectorMBean;
00053 import org.objectweb.cjdbc.common.jmx.mbeans.DatabaseBackendMBean;
00054 import org.objectweb.cjdbc.common.jmx.mbeans.VirtualDatabaseMBean;
00055 import org.objectweb.cjdbc.common.users.AdminUser;
00056 import org.objectweb.cjdbc.controller.authentication.PasswordAuthenticator;
00057
00058
00059
00060
00061
00062
00063
00064
00065 public class RmiJmxClient
00066 {
00067 private JMXConnector connector;
00068 private Object credentials;
00069 private String remoteHostAddress;
00070 private String remoteHostPort;
00071
00072 private NotificationListener notificationListener;
00073
00074
00075 private ControllerMBean controllerMBean;
00076 private VirtualDatabaseMBean virtualDbMBean;
00077 private DatabaseBackendMBean backendMBean;
00078 private DataCollectorMBean dataMBean;
00079
00080
00081
00082
00083
00084
00085 public NotificationListener getNotificationListener()
00086 {
00087 return notificationListener;
00088 }
00089
00090
00091
00092
00093
00094
00095 public void setNotificationListener(NotificationListener notificationListener)
00096 {
00097 this.notificationListener = notificationListener;
00098 }
00099
00100
00101
00102
00103
00104
00105 public Object getCredentials()
00106 {
00107 return credentials;
00108 }
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 public RmiJmxClient(String port, String host, String jmxUser,
00120 String jmxPassword) throws IOException
00121 {
00122 this(port, host, PasswordAuthenticator.createCredentials(jmxUser,
00123 jmxPassword));
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133 public RmiJmxClient(String url, Object credentials) throws IOException
00134 {
00135 int index = url.indexOf(":");
00136 String ip = url.substring(0, index);
00137 String port = url.substring(index + 1);
00138 connect(port, ip, credentials);
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 public RmiJmxClient(String port, String host, Object credentials)
00150 throws IOException
00151 {
00152 connect(port, host, credentials);
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 public void connect(String port, String host, Object credentials)
00164 throws IOException
00165 {
00166 JMXServiceURL address = new JMXServiceURL("rmi", host, 0, "/jndi/jrmp");
00167
00168 Map environment = new HashMap();
00169 environment.put(Context.INITIAL_CONTEXT_FACTORY,
00170 "com.sun.jndi.rmi.registry.RegistryContextFactory");
00171 environment.put(Context.PROVIDER_URL, "rmi://" + host + ":" + port);
00172
00173
00174
00175
00176 if (credentials != null)
00177 {
00178
00179 environment.put(JMXConnector.CREDENTIALS, credentials);
00180 }
00181
00182 this.credentials = credentials;
00183
00184 connector = JMXConnectorFactory.connect(address, environment);
00185 remoteHostAddress = host;
00186 remoteHostPort = port;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 public Set listCJDBCMBeans() throws Exception
00196 {
00197 Set set = connector.getMBeanServerConnection().queryMBeans(
00198 new ObjectName("c-jdbc:*"), null);
00199 return set;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209 public MBeanInfo getMBeanInfo(ObjectName mbean) throws Exception
00210 {
00211 return connector.getMBeanServerConnection().getMBeanInfo(mbean);
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 public Object getAttributeValue(ObjectName mbean, String attribute)
00224 throws Exception
00225 {
00226 return connector.getMBeanServerConnection().getAttribute(mbean, attribute);
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 public void setAttributeValue(ObjectName mbean, String attribute, Object value)
00238 throws Exception
00239 {
00240 Attribute att = new Attribute(attribute, value);
00241 connector.getMBeanServerConnection().setAttribute(mbean, att);
00242 }
00243
00244
00245
00246
00247
00248
00249
00250 public void setCurrentSubject(String user, String password)
00251 {
00252 if (user != null && password != null)
00253 {
00254
00255 AdminUser dbUser = new AdminUser(user, password);
00256 Set principals = new HashSet();
00257 principals.add(dbUser);
00258 subject = new Subject(true, principals, new HashSet(), new HashSet());
00259 }
00260 }
00261
00262 Subject subject;
00263
00264
00265
00266
00267
00268
00269 public boolean isSubjectSet()
00270 {
00271 return subject != null;
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 public Object invokeOperation(ObjectName name, MBeanOperationInfo operation,
00284 Object[] args) throws Exception
00285 {
00286 if (JmxConstants.mbeanNeedAuthentication(name))
00287 {
00288 if (!isSubjectSet())
00289 throw new Exception(
00290 "Subject has not been set for this jmx client, and authentication is required");
00291 return connector.getMBeanServerConnection(subject).invoke(name,
00292 operation.getName(), args, getSignature(operation));
00293 }
00294 else
00295 {
00296 return connector.getMBeanServerConnection().invoke(name,
00297 operation.getName(), args, getSignature(operation));
00298 }
00299 }
00300
00301 private String[] getSignature(MBeanOperationInfo operation)
00302 {
00303 MBeanParameterInfo[] info = operation.getSignature();
00304 String[] signature = new String[info.length];
00305 for (int i = 0; i < info.length; i++)
00306 signature[i] = info[i].getType();
00307 return signature;
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 public VirtualDatabaseMBean getVirtualDatabaseProxy(String database,
00322 String user, String password) throws InstanceNotFoundException,
00323 IOException, VirtualDatabaseException
00324 {
00325 if (virtualDbMBean != null && isValidConnection()
00326 && virtualDbMBean.getVirtualDatabaseName().equals(database))
00327 {
00328 return virtualDbMBean;
00329 }
00330 else
00331 {
00332 ObjectName db = JmxConstants.getVirtualDbObjectName(database);
00333
00334
00335 AdminUser dbUser = new AdminUser(user, password);
00336 Set principals = new HashSet();
00337 principals.add(dbUser);
00338 Subject subj = new Subject(true, principals, new HashSet(), new HashSet());
00339
00340
00341
00342 MBeanServerConnection delegateConnection = connector
00343 .getMBeanServerConnection(subj);
00344
00345
00346 VirtualDatabaseMBean local = (VirtualDatabaseMBean) MBeanServerInvocationHandler
00347 .newProxyInstance(delegateConnection, db, VirtualDatabaseMBean.class,
00348 false);
00349
00350
00351 boolean authenticated = false;
00352 try
00353 {
00354 authenticated = local.checkAdminAuthentication(user, password);
00355 }
00356 catch (Exception e)
00357 {
00358 throw new VirtualDatabaseException(
00359 "Could not check authentication. MBean is not accessible.");
00360 }
00361 if (!authenticated)
00362 throw new VirtualDatabaseException("Authentication Failed");
00363
00364
00365 if (notificationListener != null)
00366 {
00367 delegateConnection.addNotificationListener(db, notificationListener,
00368 null, null);
00369
00370
00371
00372
00373
00374
00375
00376
00377 }
00378
00379 this.virtualDbMBean = local;
00380
00381 return virtualDbMBean;
00382 }
00383 }
00384
00385
00386
00387
00388
00389
00390
00391 public ControllerMBean getControllerProxy() throws IOException
00392 {
00393
00394 if (controllerMBean != null && isValidConnection())
00395 {
00396 return controllerMBean;
00397 }
00398 else
00399 {
00400 if (!isValidConnection())
00401 reconnect();
00402
00403 ObjectName db = JmxConstants.getControllerObjectName();
00404
00405
00406 controllerMBean = (ControllerMBean) MBeanServerInvocationHandler
00407 .newProxyInstance(connector.getMBeanServerConnection(), db,
00408 ControllerMBean.class, false);
00409
00410
00411 if (notificationListener != null)
00412 {
00413 try
00414 {
00415 connector.getMBeanServerConnection().addNotificationListener(db,
00416 notificationListener, null, null);
00417 }
00418 catch (Exception e)
00419 {
00420 throw new IOException("Could not register listener on the mbean");
00421 }
00422 }
00423
00424 return controllerMBean;
00425 }
00426 }
00427
00428
00429
00430
00431
00432
00433
00434 public DataCollectorMBean getDataCollectorProxy() throws IOException
00435 {
00436
00437 if (dataMBean != null && isValidConnection())
00438 {
00439 return dataMBean;
00440 }
00441 else
00442 {
00443 if (!isValidConnection())
00444 reconnect();
00445 ObjectName db = JmxConstants.getDataCollectorObjectName();
00446
00447
00448 dataMBean = (DataCollectorMBean) MBeanServerInvocationHandler
00449 .newProxyInstance(connector.getMBeanServerConnection(), db,
00450 DataCollectorMBean.class, false);
00451 return dataMBean;
00452 }
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 public DatabaseBackendMBean getDatabaseBackendProxy(String vdb,
00467 String backend, String user, String password)
00468 throws InstanceNotFoundException, IOException
00469 {
00470 if (backendMBean != null && isValidConnection())
00471 {
00472 try
00473 {
00474 if (backendMBean.getName().equals(backend))
00475 return backendMBean;
00476 }
00477 catch (Exception e)
00478 {
00479
00480 }
00481 }
00482
00483 if (!isValidConnection())
00484 reconnect();
00485
00486
00487 AdminUser dbUser = new AdminUser(user, password);
00488 Set principals = new HashSet();
00489 principals.add(dbUser);
00490 Subject subj = new Subject(true, principals, new HashSet(), new HashSet());
00491
00492 ObjectName db = JmxConstants.getDatabaseBackendObjectName(vdb, backend);
00493 MBeanServerConnection delegateConnection = connector
00494 .getMBeanServerConnection(subj);
00495
00496 if (notificationListener != null)
00497 {
00498 delegateConnection.addNotificationListener(db, notificationListener,
00499 null, null);
00500 StringMonitor sm = new StringMonitor();
00501 sm.setObservedObject(db);
00502 sm.setObservedAttribute("LastKnownCheckpoint");
00503 sm.setStringToCompare("hello");
00504 sm.setGranularityPeriod(100);
00505 sm.setNotifyDiffer(true);
00506 sm.addNotificationListener(notificationListener, null, null);
00507 sm.start();
00508 }
00509
00510
00511 backendMBean = (DatabaseBackendMBean) MBeanServerInvocationHandler
00512 .newProxyInstance(delegateConnection, db, DatabaseBackendMBean.class,
00513 false);
00514 return backendMBean;
00515 }
00516
00517
00518
00519
00520
00521
00522
00523 public String getRemoteName()
00524 {
00525 return remoteHostAddress + ":" + remoteHostPort;
00526 }
00527
00528
00529
00530
00531
00532
00533 public String getRemoteHostAddress()
00534 {
00535 return remoteHostAddress;
00536 }
00537
00538
00539
00540
00541
00542
00543 public String getRemoteHostPort()
00544 {
00545 return remoteHostPort;
00546 }
00547
00548
00549
00550
00551
00552
00553 public void reconnect() throws IOException
00554 {
00555 connect(remoteHostPort, remoteHostAddress, credentials);
00556 }
00557
00558
00559
00560
00561
00562
00563 public boolean isValidConnection()
00564 {
00565 try
00566 {
00567 connector.getMBeanServerConnection().getMBeanCount();
00568 return true;
00569 }
00570 catch (Exception e)
00571 {
00572 controllerMBean = null;
00573 backendMBean = null;
00574 virtualDbMBean = null;
00575 dataMBean = null;
00576 return false;
00577 }
00578 }
00579 }