Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

CjdbcGui.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2005 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Nicolas Modrzyk
00022  * Contributor(s): Emmanuel Cecchet.
00023  */
00024 
00025 package org.objectweb.cjdbc.console.gui;
00026 
00027 import java.awt.BorderLayout;
00028 import java.awt.Color;
00029 import java.awt.Container;
00030 import java.awt.Cursor;
00031 import java.awt.Dimension;
00032 import java.awt.FlowLayout;
00033 import java.awt.GridLayout;
00034 import java.awt.dnd.DnDConstants;
00035 import java.awt.dnd.DropTarget;
00036 import java.io.BufferedReader;
00037 import java.io.BufferedWriter;
00038 import java.io.File;
00039 import java.io.FileInputStream;
00040 import java.io.FileNotFoundException;
00041 import java.io.FileReader;
00042 import java.io.FileWriter;
00043 import java.io.IOException;
00044 import java.io.PrintWriter;
00045 import java.io.StringReader;
00046 import java.text.SimpleDateFormat;
00047 import java.util.ArrayList;
00048 import java.util.Date;
00049 import java.util.Enumeration;
00050 import java.util.HashMap;
00051 import java.util.Hashtable;
00052 import java.util.Iterator;
00053 import java.util.Set;
00054 
00055 import javax.management.MBeanAttributeInfo;
00056 import javax.management.MBeanException;
00057 import javax.management.MBeanInfo;
00058 import javax.management.MBeanOperationInfo;
00059 import javax.management.ObjectInstance;
00060 import javax.management.ObjectName;
00061 import javax.swing.BorderFactory;
00062 import javax.swing.Icon;
00063 import javax.swing.JButton;
00064 import javax.swing.JDesktopPane;
00065 import javax.swing.JFileChooser;
00066 import javax.swing.JFrame;
00067 import javax.swing.JInternalFrame;
00068 import javax.swing.JOptionPane;
00069 import javax.swing.JPanel;
00070 import javax.swing.JScrollPane;
00071 import javax.swing.JTabbedPane;
00072 import javax.swing.JTable;
00073 import javax.swing.JTextArea;
00074 import javax.swing.JTextField;
00075 import javax.swing.JTextPane;
00076 import javax.swing.JToolTip;
00077 import javax.swing.filechooser.FileFilter;
00078 
00079 import org.objectweb.cjdbc.common.exceptions.CJDBCException;
00080 import org.objectweb.cjdbc.common.i18n.ConsoleTranslate;
00081 import org.objectweb.cjdbc.common.i18n.GuiTranslate;
00082 import org.objectweb.cjdbc.common.jmx.JmxException;
00083 import org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean;
00084 import org.objectweb.cjdbc.common.jmx.mbeans.DataCollectorMBean;
00085 import org.objectweb.cjdbc.common.jmx.mbeans.DatabaseBackendMBean;
00086 import org.objectweb.cjdbc.common.jmx.mbeans.VirtualDatabaseMBean;
00087 import org.objectweb.cjdbc.common.jmx.notifications.CjdbcNotificationList;
00088 import org.objectweb.cjdbc.common.shared.BackendInfo;
00089 import org.objectweb.cjdbc.common.util.Constants;
00090 import org.objectweb.cjdbc.common.util.Strings;
00091 import org.objectweb.cjdbc.common.xml.XmlTools;
00092 import org.objectweb.cjdbc.console.gui.constants.GuiCommands;
00093 import org.objectweb.cjdbc.console.gui.constants.GuiConstants;
00094 import org.objectweb.cjdbc.console.gui.constants.GuiIcons;
00095 import org.objectweb.cjdbc.console.gui.dnd.listeners.BackendTransferListener;
00096 import org.objectweb.cjdbc.console.gui.dnd.listeners.ControllerTransferListener;
00097 import org.objectweb.cjdbc.console.gui.frames.GuiExceptionFrame;
00098 import org.objectweb.cjdbc.console.gui.frames.GuiInputBackupFrame;
00099 import org.objectweb.cjdbc.console.gui.frames.GuiNewControllerFrame;
00100 import org.objectweb.cjdbc.console.gui.frames.GuiSelectCheckpointFrame;
00101 import org.objectweb.cjdbc.console.gui.frames.GuiSelectShutdownFrame;
00102 import org.objectweb.cjdbc.console.gui.frames.GuiVirtualDatabaseLoginFrame;
00103 import org.objectweb.cjdbc.console.gui.frames.NewBackendFrame;
00104 import org.objectweb.cjdbc.console.gui.frames.jmxdesktop.AttributeChangeDialog;
00105 import org.objectweb.cjdbc.console.gui.frames.jmxdesktop.OperationCallDialog;
00106 import org.objectweb.cjdbc.console.gui.jtools.JMultiLineToolTip;
00107 import org.objectweb.cjdbc.console.gui.jtools.JTextAreaWriter;
00108 import org.objectweb.cjdbc.console.gui.model.AttributeModel;
00109 import org.objectweb.cjdbc.console.gui.model.JNewList;
00110 import org.objectweb.cjdbc.console.gui.model.OperationModel;
00111 import org.objectweb.cjdbc.console.gui.objects.BackendObject;
00112 import org.objectweb.cjdbc.console.gui.objects.ConfigurationFileObject;
00113 import org.objectweb.cjdbc.console.gui.objects.ControllerObject;
00114 import org.objectweb.cjdbc.console.gui.objects.DatabaseObject;
00115 import org.objectweb.cjdbc.console.gui.objects.DumpFileObject;
00116 import org.objectweb.cjdbc.console.gui.objects.tooltips.BackendToolTip;
00117 import org.objectweb.cjdbc.console.gui.popups.ConfigurationFilePopUpMenu;
00118 import org.objectweb.cjdbc.console.gui.popups.ControllerListPopUpMenu;
00119 import org.objectweb.cjdbc.console.gui.popups.ControllerPopUpMenu;
00120 import org.objectweb.cjdbc.console.gui.popups.DatabasePopUpMenu;
00121 import org.objectweb.cjdbc.console.gui.popups.DumpPopUpMenu;
00122 import org.objectweb.cjdbc.console.gui.popups.LogEditPopUpMenu;
00123 import org.objectweb.cjdbc.console.gui.session.GuiSession;
00124 import org.objectweb.cjdbc.console.gui.threads.GuiLoggingThread;
00125 import org.objectweb.cjdbc.console.gui.threads.GuiParsingThread;
00126 import org.objectweb.cjdbc.console.gui.threads.task.BackupBackendTask;
00127 import org.objectweb.cjdbc.console.gui.threads.task.RestoreBackendTask;
00128 import org.objectweb.cjdbc.console.jmx.RmiJmxClient;
00129 import org.objectweb.cjdbc.console.monitoring.MonitoringConsole;
00130 import org.objectweb.cjdbc.console.text.ConsoleException;
00131 import org.objectweb.cjdbc.console.views.CacheStatsViewer;
00132 import org.objectweb.cjdbc.console.views.CacheViewer;
00133 import org.objectweb.cjdbc.console.views.RecoveryLogViewer;
00134 import org.objectweb.cjdbc.console.views.SQLStatViewer;
00135 
00136 /**
00137  * This class is the main class for the graphical version of the C-JDBC
00138  * administration console.
00139  * 
00140  * @author <a href="mailto:Nicolas.Modrzyk@inria.fr">Nicolas Modrzyk </a>
00141  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00142  * @version 1.0
00143  */
00144 public class CjdbcGui extends JFrame
00145 {
00146   // /////////////////////////////////////////////////////////////
00147   // DATA CONTAINERS
00148   // /////////////////////////////////////////////////////////////
00149   /** Stored values for session */
00150   GuiSession                   guiSession;
00151   /** Virtual database MBeans [DatabaseName] / [VirtualDatabaseJmxClient] */
00152   Hashtable                    databaseMBeans;
00153   /** Controller MBeans [URL] / [ControllerJmxClient] */
00154   Hashtable                    controllerMBeans;
00155   /** Hastable of backends states: [StateName] / [Panel] */
00156   Hashtable                    backendsState;
00157   /** List of backends [backendName] : [BackendObject] */
00158   Hashtable                    backendList;
00159   /** List of databases [databaseName] : [DatabaseObject] */
00160   Hashtable                    databaseList;
00161   /** List of controllers [controllerName] : [ControllerObject] */
00162   Hashtable                    controllerList;
00163 
00164   /** List of jmx clients [url] : [RmiJmxClient] */
00165   Hashtable                    jmxClients;
00166   RmiJmxClient                 currentJmxClient;
00167   String                       selectedController;
00168   String                       selectedDatabase;
00169 
00170   Object                       credentials = null;
00171 
00172   JNewList                     mbeanList;
00173 
00174   // /////////////////////////////////////////////////////////////
00175   // THREADS
00176   // /////////////////////////////////////////////////////////////
00177   /** The thread that connects to the log4j server on a host */
00178   GuiLoggingThread             logginThread;
00179 
00180   // /////////////////////////////////////////////////////////////
00181   // MIXED CONTAINERS
00182   // /////////////////////////////////////////////////////////////
00183   /** The panel for the list of databases */
00184   JPanel                       vdbListPanel;
00185   /** The list containing the xml file NAMES, no paths */
00186   JPanel                       fileListPanel;
00187   /** Panel for controller list */
00188   JPanel                       controllerListPanel;
00189 
00190   // /////////////////////////////////////////////////////////////
00191   // FLOATING FRAMES
00192   // /////////////////////////////////////////////////////////////
00193   /** Login frame */
00194   GuiVirtualDatabaseLoginFrame loginFrame;
00195   /** New controller frame objects */
00196   GuiNewControllerFrame        newControllerFrame;
00197   /** Exception frame for reporting errors from the server */
00198   GuiExceptionFrame            exceptionFrame;
00199   /** New Backend frame object */
00200   NewBackendFrame              newBackendFrame;
00201   /** Select checkpoint frame */
00202   GuiSelectCheckpointFrame     selectCheckpointFrame;
00203   /** Select shutdown frame */
00204   GuiSelectShutdownFrame       selectShutdownFrame;
00205   /** Select backup frame */
00206   GuiInputBackupFrame          inputBackupFrame;
00207 
00208   // /////////////////////////////////////////////////////////////
00209   // LISTENERS
00210   // /////////////////////////////////////////////////////////////
00211   /** Backend transfer listener used for drag and drop */
00212   BackendTransferListener      backendTransferListener;
00213   /** Configuration File transfer listener used for drag and drop */
00214   ControllerTransferListener   configurationFileTransferListener;
00215 
00216   /** GuiAction listener */
00217   CjdbcGuiListener             guiActionListener;
00218 
00219   // /////////////////////////////////////////////////////////////
00220   // GRAPHIC CONTAINERS
00221   // /////////////////////////////////////////////////////////////
00222 
00223   /** The texts of the debug,logging panel */
00224   String                       debugText, loggingText;
00225   /** The debug panel itself */
00226   JTextArea                    debugTextPane, loggingTextPane;
00227   /** The log panel itself */
00228   JTextPane                    infoTextPane;
00229   /** The thread that parse the xml panel */
00230   GuiParsingThread             parsingThread;
00231   /** The xml editor panel */
00232   JTextPane                    xmlTextPane;
00233   /** the file chooser for configuration files */
00234   JFileChooser                 configurationFileChooser;
00235   /** the file chooser for jar files */
00236   JFileChooser                 jarFileChooser;
00237   /** the save file chooser for files */
00238   JFileChooser                 saveFileChooser;
00239   /** Backend pane */
00240   JPanel                       backendPanel;
00241   /** The controller list mouse listener */
00242   ControllerListPopUpMenu      controllerListPopUpMenu;
00243   /** The center Pane */
00244   JTabbedPane                  centerPane;
00245   /** Scroll panel for selection in center pane */
00246   JScrollPane                  helpScroll, debugScroll, xmlScroll,
00247       loggingScroll, infoScroll, logConfigScroll;
00248   /** Scroll panels from the left pane */
00249   JScrollPane                  fileScroll;
00250   /** The panel for exceptions tracing */
00251   JTextArea                    debugTraceTextPane;
00252   /** Writer to the trace exception area in the backend panel */
00253   JTextAreaWriter              traceWriter;
00254   /** The panel for the log4j configuration */
00255   JTextPane                    logConfigTextPane;
00256   /** Panels for the backend panel */
00257   JPanel                       backendButtons, backendIcons;
00258 
00259   JDesktopPane                 jmxPanel;
00260   JScrollPane                  jmxScroll;
00261   JScrollPane                  attributePane;
00262   JTable                       attributeTable;
00263   JTable                       operationTable;
00264   JScrollPane                  operationPane;
00265 
00266   JInternalFrame               mbeanFrame;
00267   JInternalFrame               attributeFrame;
00268   JInternalFrame               operationFrame;
00269 
00270   /**
00271    * Creates a new <code>CjdbcGui.java</code> object
00272    */
00273   public CjdbcGui()
00274   {
00275     super(GuiTranslate.get("gui.name"));
00276     new Thread(new CjdbcGuiLoader(this)).start();
00277   }
00278 
00279   private ControllerMBean actionGetControllerBean(String controllerName)
00280   {
00281     if (controllerMBeans.containsKey(controllerName))
00282     {
00283       currentJmxClient = (RmiJmxClient) jmxClients.get(controllerName);
00284       if (currentJmxClient.isValidConnection())
00285       {
00286         ControllerMBean controllerMBean = (ControllerMBean) controllerMBeans
00287             .get(controllerName);
00288         ((ControllerObject) controllerList.get(controllerName))
00289             .setIcon(GuiIcons.CONTROLLER_READY);
00290         return controllerMBean;
00291       }
00292       else
00293       {
00294         appendDebugText("Controller :" + controllerName
00295             + " cannot be accessed anymore. Trying to reconnect...");
00296         controllerMBeans.remove(controllerName);
00297         return actionGetControllerBean(controllerName);
00298       }
00299     }
00300     else
00301     {
00302       try
00303       {
00304         RmiJmxClient jmxClient = new RmiJmxClient(controllerName, credentials);
00305         appendDebugText("Setting listener for controller:" + controllerName);
00306         jmxClient.setNotificationListener(guiActionListener);
00307         jmxClients.put(controllerName, jmxClient);
00308         controllerMBeans.put(controllerName, jmxClient.getControllerProxy());
00309         if (selectedController == null
00310             || controllerName.equalsIgnoreCase(selectedController))
00311           currentJmxClient = jmxClient;
00312 
00313         appendDebugText("Connected to: " + controllerName);
00314         actionStartControllerLoggingThread(controllerName);
00315 
00316         ControllerObject co = ((ControllerObject) controllerList
00317             .get(controllerName));
00318         if (co != null)
00319           co.setIcon(GuiIcons.CONTROLLER_READY);
00320         return jmxClient.getControllerProxy();
00321       }
00322       catch (Exception e)
00323       {
00324         appendDebugText("Failed to connect to: " + controllerName);
00325         ControllerObject co = ((ControllerObject) controllerList
00326             .get(controllerName));
00327         if (co != null)
00328           co.setIcon(GuiIcons.CONTROLLER_DOWN);
00329         return null;
00330       }
00331     }
00332   }
00333 
00334   private void actionStartControllerLoggingThread(String controllerName)
00335   {
00336     try
00337     {
00338       RmiJmxClient client = (RmiJmxClient) jmxClients.get(controllerName);
00339       String ip = client.getRemoteHostAddress();
00340 
00341       if (logginThread != null)
00342         logginThread.quit();
00343       logginThread = new GuiLoggingThread(loggingTextPane, ip);
00344       logginThread.start();
00345       appendDebugText("Log4j logging thread started for: <" + controllerName
00346           + ">");
00347     }
00348     catch (Exception e1)
00349     {
00350       e1.printStackTrace();
00351       appendDebugText("Could not start log4j logging thread to: <"
00352           + controllerName + ">");
00353     }
00354   }
00355 
00356   private VirtualDatabaseMBean actionGetDatabaseBean(String databaseName)
00357   {
00358     if (databaseMBeans.containsKey(databaseName))
00359     {
00360       return (VirtualDatabaseMBean) databaseMBeans.get(databaseName);
00361     }
00362     else
00363     {
00364       appendDebugText("Login to database:" + databaseName);
00365       DatabaseObject dob = (DatabaseObject) databaseList.get(databaseName);
00366       if (dob == null)
00367       {
00368         appendDebugText("Failed to retrieve " + databaseName
00369             + " from internal list");
00370         return null;
00371       }
00372       loginFrame = new GuiVirtualDatabaseLoginFrame(this, guiActionListener,
00373           databaseName, dob.getIpAdress(), dob.getPort(), guiSession);
00374       loginFrame.setVisible(true);
00375       return null;
00376     }
00377   }
00378 
00379   private void actionLoadDatabaseList(String controllerName)
00380   {
00381     // /////////////////////////////////////////////////////////////////////////
00382     // Load list of database
00383     // /////////////////////////////////////////////////////////////////////////
00384     ControllerMBean controllerMBean = actionGetControllerBean(controllerName);
00385     ArrayList databases;
00386     try
00387     {
00388       vdbListPanel.removeAll();
00389       databases = controllerMBean.getVirtualDatabaseNames();
00390       int size = databases.size();
00391       appendDebugText("Loading virtual databases list...");
00392       for (int i = 0; i < size; i++)
00393         actionLoadDatabase((String) databases.get(i), controllerName);
00394     }
00395     catch (Exception e1)
00396     {
00397       e1.printStackTrace();
00398       appendDebugText("Cannot load virtual database list (" + e1.getMessage()
00399           + ")");
00400       vdbListPanel.removeAll();
00401     }
00402     paintDatabasePanel();
00403     repaint();
00404   }
00405 
00406   void actionUnloadBackends(String controller)
00407   {
00408     appendDebugText("Unloading backends from controller:" + controller);
00409     Enumeration enume;
00410     BackendObject bo;
00411     String name;
00412     while ((enume = backendList.keys()).hasMoreElements())
00413     {
00414       name = (String) enume.nextElement();
00415       bo = (BackendObject) backendList.get(name);
00416       bo.setVisible(false);
00417       backendList.remove(name);
00418       bo = null;
00419     }
00420   }
00421 
00422   void paintDatabasePanel()
00423   {
00424     vdbListPanel.validate();
00425     vdbListPanel.repaint();
00426     validate();
00427     repaint();
00428   }
00429 
00430   private void actionLoadDatabase(String databaseName, String controllerName)
00431   {
00432     // /////////////////////////////////////////////////////////////////////////
00433     // Load graphic object for a virtual database
00434     // /////////////////////////////////////////////////////////////////////////
00435     DatabaseObject dob = new DatabaseObject(databaseName, controllerName, false);
00436     dob.setActionCommand(GuiCommands.COMMAND_SELECT_DATABASE);
00437     dob.addActionListener(guiActionListener);
00438     dob.addMouseListener(new DatabasePopUpMenu(this, dob));
00439     databaseList.put(databaseName, dob);
00440     // We need the object to be in the list before calling getDatabaseBean
00441     VirtualDatabaseMBean virtualDatabaseMBean = actionGetDatabaseBean(databaseName);
00442     if (virtualDatabaseMBean != null)
00443       dob.setDistributed(virtualDatabaseMBean.isDistributed());
00444     actionAddObjectToGridLayout(vdbListPanel, dob);
00445     appendDebugText("Loaded:" + databaseName + " for controller:"
00446         + controllerName);
00447   }
00448 
00449   private void actionAddObjectToGridLayout(JPanel panel, JButton button)
00450   {
00451     GridLayout layout = (GridLayout) panel.getLayout();
00452     int pcount = panel.getComponentCount();
00453     layout.setRows(pcount + 1);
00454     panel.add(button);
00455     panel.validate();
00456     panel.repaint();
00457   }
00458 
00459   /**
00460    * Load the list of backends for the given database
00461    * 
00462    * @param databaseName the database to load the backends from
00463    */
00464   public void publicActionLoadBackendsList(String databaseName)
00465   {
00466     try
00467     {
00468       VirtualDatabaseMBean databaseMBean = actionGetDatabaseBean(databaseName);
00469       // ArrayList list = actionLoadCheckpointNames(databaseName);
00470       ArrayList backends = databaseMBean.getAllBackendNames();
00471       appendDebugText("Local Backend list for controller("
00472           + currentJmxClient.getRemoteName() + ") is:" + backends);
00473       for (int i = 0; i < backends.size(); i++)
00474         actionLoadBackend(databaseName, (String) backends.get(i),
00475             currentJmxClient.getRemoteName(), true);
00476 
00477       if (databaseMBean.isDistributed())
00478       {
00479         databaseMBean = actionGetDatabaseBean(databaseName);
00480         Hashtable map;
00481         try
00482         {
00483           map = databaseMBean.viewGroupBackends();
00484           Enumeration enumeration = map.keys();
00485           while (enumeration.hasMoreElements())
00486           {
00487             String controllerName = (String) enumeration.nextElement();
00488             ArrayList list = (ArrayList) map.get(controllerName);
00489             for (int i = 0; i < list.size(); i++)
00490             {
00491               BackendInfo info = (BackendInfo) list.get(i);
00492               String backendName = info.getName();
00493               actionLoadBackend(databaseName, backendName, controllerName,
00494                   false);
00495             }
00496           }
00497         }
00498         catch (RuntimeException e1)
00499         {
00500           appendDebugText(
00501               "Runtime exception while loading distributed database:"
00502                   + databaseName, e1);
00503         }
00504 
00505       }
00506       paintBackendPane();
00507     }
00508     catch (Exception e)
00509     {
00510       appendDebugText("Could not retrieve backend list for database"
00511           + databaseName, e);
00512     }
00513   }
00514 
00515   /**
00516    * Create a new database backend object and load its state
00517    * 
00518    * @param database the virtual database name
00519    * @param backendName the backend name
00520    * @param controllerName the controller that owns this backend
00521    * @param enable if the backend object should be enabled. (not used?)
00522    */
00523   public void actionLoadBackend(String database, String backendName,
00524       String controllerName, boolean enable)
00525   {
00526     BackendObject backend = null;
00527     if (!backendList.containsKey(backendName))
00528     {
00529       appendDebugText("Loading backend:" + backendName + " from controller:"
00530           + controllerName);
00531       try
00532       {
00533         backend = new BackendObject(this, backendTransferListener, database,
00534             backendName, controllerName)
00535         {
00536           public JToolTip createToolTip()
00537           {
00538             return new JMultiLineToolTip();
00539           }
00540         };
00541       }
00542       catch (Exception e)
00543       {
00544         e.printStackTrace();
00545       }
00546       backend.setBorder(BorderFactory.createTitledBorder(
00547           GuiConstants.LOWERED_BORDER, controllerName));
00548       backend.setControllerName(controllerName);
00549       backendList.put(backendName, backend);
00550     }
00551     else
00552     {
00553       backend = (BackendObject) backendList.get(backendName);
00554       backend.setBorder(BorderFactory.createTitledBorder(
00555           GuiConstants.LOWERED_BORDER, controllerName));
00556       backend.setControllerName(controllerName);
00557       backend.setEnabled(controllerName.equals(selectedController));
00558       appendDebugText("ReLoading backend:" + backendName);
00559     }
00560 
00561     try
00562     {
00563       actionSetBackendState(backendName);
00564     }
00565     catch (RuntimeException e)
00566     {
00567       appendDebugText("cannot access mbean anymore");
00568       publicActionRemoveBackendFromGui(backendName);
00569     }
00570   }
00571 
00572   /**
00573    * Converts a JMX state to a Gui constants values
00574    * 
00575    * @param jmxState the JMX state to convert
00576    * @return the GUI constant value or null if not found
00577    * @see GuiConstants
00578    */
00579   private String actionConvertState(String jmxState)
00580   {
00581     if (jmxState == null)
00582       return null;
00583 
00584     appendDebugText("Converting new jmx state:" + jmxState);
00585 
00586     if (jmxState
00587         .equalsIgnoreCase(CjdbcNotificationList.VIRTUALDATABASE_BACKEND_ENABLED))
00588       return GuiConstants.BACKEND_STATE_ENABLED;
00589     else if (jmxState
00590         .equalsIgnoreCase(CjdbcNotificationList.VIRTUALDATABASE_BACKEND_ENABLED_WRITE))
00591       return GuiConstants.BACKEND_STATE_ENABLED;
00592     else if (jmxState
00593         .equalsIgnoreCase(CjdbcNotificationList.VIRTUALDATABASE_BACKEND_DISABLED))
00594       return GuiConstants.BACKEND_STATE_DISABLED;
00595     else if (jmxState
00596         .equalsIgnoreCase(CjdbcNotificationList.VIRTUALDATABASE_BACKEND_DISABLING))
00597       return GuiConstants.BACKEND_STATE_DISABLED;
00598     else if (jmxState
00599         .equalsIgnoreCase(CjdbcNotificationList.VIRTUALDATABASE_BACKEND_BACKINGUP))
00600       return GuiConstants.BACKEND_STATE_BACKUP;
00601     else if (jmxState
00602         .equalsIgnoreCase(CjdbcNotificationList.VIRTUALDATABASE_BACKEND_RECOVERING))
00603       return GuiConstants.BACKEND_STATE_RESTORE;
00604     else if (jmxState
00605         .equalsIgnoreCase(CjdbcNotificationList.VIRTUALDATABASE_BACKEND_REPLAYING))
00606       return GuiConstants.BACKEND_STATE_RECOVERY;
00607     else if (jmxState
00608         .equalsIgnoreCase(CjdbcNotificationList.VIRTUALDATABASE_BACKEND_UNKNOWN))
00609       return GuiConstants.BACKEND_STATE_DISABLED;
00610     else
00611       return null;
00612   }
00613 
00614   /**
00615    * Change the state of a backend object Checks the new state is valid, and
00616    * then display the backend object into the new panel. Removes it from the old
00617    * panel as well. Calls repaint of each panel. This is not connected to the
00618    * actual database the backend object is referenced from because many states
00619    * do not exist on the controller
00620    * 
00621    * @param bo the backend object
00622    * @param newState new state to assign to the backend
00623    */
00624   public void actionChangeBackendState(BackendObject bo, String newState)
00625   {
00626     // test if the new state is valid
00627     if (!GuiConstants.isValidBackendState(newState))
00628       return;
00629 
00630     // State is valid, process
00631 
00632     // Removed from old panel
00633     String oldState = bo.getState();
00634     JPanel oldpanel = (JPanel) backendsState.get(oldState);
00635     oldpanel.remove(bo);
00636     oldpanel.validate();
00637     oldpanel.repaint();
00638 
00639     // Change the state of the backend object
00640     bo.setState(newState);
00641 
00642     // Add it to thew new state panel
00643     JPanel panel = (JPanel) backendsState.get(newState);
00644     panel.add(bo);
00645     panel.validate();
00646     panel.repaint();
00647   }
00648 
00649   /**
00650    * Set the state of the given backend. The state is retrieved via a jmx call
00651    * on the backend corresponding MBean.
00652    * 
00653    * @param backendName the backend to set the state
00654    */
00655   public void actionSetBackendState(String backendName)
00656   {
00657     try
00658     {
00659       BackendObject bo = (BackendObject) backendList.get(backendName);
00660       if (bo == null)
00661       {
00662         appendDebugText("Backend (" + backendName + ") cannot be found");
00663         return;
00664       }
00665       String controllerName = bo.getControllerName();
00666       if (controllerName == null)
00667       {
00668         appendDebugText("Backend (" + backendName
00669             + ") has lost its controller reference.");
00670         appendDebugText("Removing backend (" + backendName
00671             + ") from display list.");
00672         backendList.remove(backendName);
00673         return;
00674       }
00675       if (selectedController.equals(controllerName))
00676         bo.setEnabled(true);
00677       else
00678         bo.setEnabled(false);
00679       String state = bo.getState();
00680       appendDebugText("STATE:" + state);
00681       String login = guiSession.getAuthenticatedDatabaseLogin(bo.getDatabase());
00682       String password = guiSession.getAuthenticatedDatabasePassword(bo
00683           .getDatabase());
00684       RmiJmxClient client = (RmiJmxClient) jmxClients.get(controllerName);
00685       DatabaseBackendMBean backend = null;
00686       VirtualDatabaseMBean databaseMBean = null;
00687 
00688       try
00689       {
00690         backend = client.getDatabaseBackendProxy(bo.getDatabase(), backendName,
00691             login, password);
00692         databaseMBean = client.getVirtualDatabaseProxy(bo.getDatabase(), login,
00693             password);
00694       }
00695       catch (Exception e)
00696       {
00697         appendDebugText("Could not change state of backend:" + backendName,
00698             new JmxException("MBean connection was lost"));
00699       }
00700       String newState = actionConvertState(backend.getState());
00701 
00702       actionSetBackendState(backendName, newState);
00703 
00704       // set Tool tip after state
00705       try
00706       {
00707         String[] data = databaseMBean.viewBackendInformation(backendName);
00708         bo.setToolTipText(new BackendToolTip(data).getFormattedToolTip());
00709       }
00710       catch (Exception e)
00711       {
00712         appendDebugText("Tool tip could not be collected for backend:"
00713             + backendName);
00714       }
00715     }
00716     catch (Exception e)
00717     {
00718       appendDebugText("Could not change state of backend:" + backendName, e);
00719     }
00720   }
00721 
00722   /**
00723    * Change panel of backend
00724    * 
00725    * @param backendName name of backend
00726    * @param newState new state
00727    */
00728   public void actionSetBackendState(String backendName, String newState)
00729   {
00730     BackendObject bo = (BackendObject) backendList.get(backendName);
00731     appendDebugText("Setting backend(" + backendName + "):" + bo.getName()
00732         + " to state:" + newState);
00733 
00734     String state = bo.getState();
00735     if (state == null)
00736     {
00737       // state has not been inited
00738     }
00739     else
00740     {
00741       // remove previous state
00742       JPanel panel = (JPanel) backendsState.get(state);
00743       panel.remove(bo);
00744       panel.validate();
00745       panel.repaint();
00746     }
00747 
00748     // Set new state
00749     JPanel panel = (JPanel) backendsState.get(newState);
00750     bo.setState(newState);
00751 
00752     panel.add(bo);
00753     panel.validate();
00754     panel.repaint();
00755 
00756   }
00757 
00758   /**
00759    * Validate and Repaint the backend split
00760    */
00761   public void paintBackendPane()
00762   {
00763     // ////////////////////////////////////////////////////////////////////////
00764     // Paint backends panel
00765     // /////////////////////////////////////////////////////////////////////////
00766     backendPanel.validate();
00767     backendPanel.repaint();
00768   }
00769 
00770   void paintConfigurationPane()
00771   {
00772     // ////////////////////////////////////////////////////////////////////////
00773     // Paint configuration file panel
00774     // /////////////////////////////////////////////////////////////////////////
00775     fileScroll.setVisible(true);
00776     fileListPanel.setVisible(true);
00777     fileScroll.validate();
00778     fileListPanel.validate();
00779     fileScroll.repaint();
00780   }
00781 
00782   String actionLoadXmlText(File filePath)
00783   {
00784     // /////////////////////////////////////////////////////////////////////////
00785     // Load xml file content
00786     // /////////////////////////////////////////////////////////////////////////
00787     try
00788     {
00789       if (filePath == null || !filePath.exists())
00790       {
00791         return "";
00792       }
00793       StringBuffer buffer = new StringBuffer();
00794       BufferedReader reader = new BufferedReader(new FileReader(filePath));
00795       String line = "";
00796       while ((line = reader.readLine()) != null)
00797       {
00798         buffer.append(line + System.getProperty("line.separator"));
00799       }
00800       reader.close();
00801       return buffer.toString();
00802     }
00803     catch (Exception e)
00804     {
00805       appendDebugText("Error while reading from file:" + e.getMessage());
00806       return "";
00807     }
00808   }
00809 
00810   /**
00811    * Append debug text to the debug panel
00812    * 
00813    * @param text to append
00814    */
00815   public void appendDebugText(String text)
00816   {
00817     debugText += text + System.getProperty("line.separator");
00818     debugTextPane.setText(debugText);
00819   }
00820 
00821   /**
00822    * Same as above and displays the stack trace ...
00823    * 
00824    * @param text text to display
00825    * @param e the exception to get the trace from
00826    */
00827   public void appendDebugText(String text, Exception e)
00828   {
00829     try
00830     {
00831       if (GuiConstants.DEBUG_LEVEL <= GuiConstants.DEBUG_NO_EXCEPTION_WINDOW)
00832       {
00833         if (e instanceof MBeanException)
00834           exceptionFrame.showException(((MBeanException) e)
00835               .getTargetException());
00836         else
00837           exceptionFrame.showException(e);
00838       }
00839       appendDebugText(text + "[Message:" + e.getMessage() + "]");
00840       traceWriter.write("---- Exception ----\n");
00841       e.printStackTrace(new PrintWriter(traceWriter));
00842       traceWriter.flush();
00843     }
00844     catch (IOException e1)
00845     {
00846       // ignore . . .
00847     }
00848   }
00849 
00850   /**
00851    * Show the file chooser to add an xml file to the configuration list
00852    */
00853   public void publicActionAddXmlFile()
00854   {
00855     if (configurationFileChooser == null)
00856     {
00857       configurationFileChooser = new JFileChooser(".");
00858       configurationFileChooser.setFileFilter(new FileFilter()
00859       {
00860         /**
00861          * @see javax.swing.filechooser.FileFilter#accept(java.io.File)
00862          */
00863         public boolean accept(File f)
00864         {
00865           if (f.getAbsolutePath().endsWith(".xml") || f.isDirectory())
00866             return true;
00867           else
00868             return false;
00869         }
00870 
00871         /**
00872          * @see javax.swing.filechooser.FileFilter#getDescription()
00873          */
00874         public String getDescription()
00875         {
00876           return "Xml Files";
00877         }
00878       });
00879     }
00880     configurationFileChooser.showOpenDialog(this);
00881     File selFile = configurationFileChooser.getSelectedFile();
00882     if (selFile != null)
00883     {
00884       appendDebugText("Selected new file:" + selFile.getAbsolutePath());
00885       guiSession.addFileToConfigurationFiles(selFile);
00886       ConfigurationFileObject cfo = new ConfigurationFileObject(
00887           configurationFileTransferListener, selFile);
00888       ConfigurationFilePopUpMenu cfpum = new ConfigurationFilePopUpMenu(this,
00889           cfo);
00890       cfo.addActionListener(cfpum);
00891       cfo.addMouseListener(cfpum);
00892       actionAddObjectToGridLayout(fileListPanel, cfo);
00893       paintConfigurationPane();
00894     }
00895   }
00896 
00897   void actionLoadXmlList()
00898   {
00899     if (fileListPanel != null)
00900     {
00901       ArrayList vfileItems = guiSession.getConfigurationFiles();
00902       int vsize = vfileItems.size();
00903       ConfigurationFileObject cfo;
00904       for (int i = 0; i < vsize; i++)
00905       {
00906         cfo = new ConfigurationFileObject(configurationFileTransferListener,
00907             (File) vfileItems.get(i));
00908         ConfigurationFilePopUpMenu cfpum = new ConfigurationFilePopUpMenu(this,
00909             cfo);
00910         cfo.addActionListener(cfpum);
00911         cfo.addMouseListener(cfpum);
00912         fileListPanel.add(cfo);
00913         actionAddObjectToGridLayout(fileListPanel, cfo);
00914       }
00915       // paintConfigurationPane();
00916     }
00917   }
00918 
00919   private ArrayList actionLoadCheckpointNames(String databaseName)
00920   {
00921     ArrayList list = actionGetDatabaseBean(databaseName).viewCheckpointNames();
00922     for (int i = 0; i < list.size(); i++)
00923       appendDebugText("Found checkpoint:" + list.get(i) + " for database:"
00924           + databaseName);
00925     return list;
00926   }
00927 
00928   /**
00929    * Load the controller list. Removes all the controller icons from the panel.
00930    * and get all the controllers from the session hashtable Then calls
00931    * <code>actionLoadController</code>
00932    */
00933   public void publicActionLoadControllerList()
00934   {
00935     if (controllerListPanel != null)
00936     {
00937       controllerListPanel.removeAll();
00938       ArrayList controllerItems = guiSession.getControllerItems();
00939       int size = controllerItems.size();
00940       for (int i = 0; i < size; i++)
00941         actionLoadController((String) controllerItems.get(i));
00942       paintControllerPane();
00943     }
00944   }
00945 
00946   /**
00947    * Paint the controller panel
00948    */
00949   void paintControllerPane()
00950   {
00951     controllerListPanel.validate();
00952     controllerListPanel.repaint();
00953   }
00954 
00955   /**
00956    * View the controller frame to add a new controller reference to the list
00957    */
00958   public void publicActionAddControllerView()
00959   {
00960     newControllerFrame.setVisible(true);
00961   }
00962 
00963   /**
00964    * actionDatabaseEnableAll definition. Call the proper MBean to enable all
00965    * backends
00966    * 
00967    * @param databaseName the name of the database to operate
00968    */
00969   public void publicActionDatabaseEnableAll(String databaseName)
00970   {
00971     try
00972     {
00973       actionGetDatabaseBean(databaseName).enableAllBackends();
00974       publicActionLoadBackendsList(databaseName);
00975       centerPane.setSelectedComponent(backendPanel);
00976       appendDebugText("Enabled All backends for :" + databaseName
00977           + " was a success");
00978     }
00979     catch (Exception e)
00980     {
00981       appendDebugText("Enabled All backends for :" + databaseName + " failed",
00982           e);
00983     }
00984   }
00985 
00986   /**
00987    * Load a panel for the backends
00988    * 
00989    * @param name the name of the panel
00990    */
00991   public void actionLoadBackendActionButton(String name)
00992   {// ////////////////////////////////////////////////////////////////////////
00993     // Define backend action buttons
00994     // /////////////////////////////////////////////////////////////////////////
00995     appendDebugText("Loading backend action panel:" + name);
00996     Color color = GuiConstants.getBackendBgColor(name);
00997 
00998     JPanel paneContent = new JPanel(new FlowLayout());
00999     paneContent.setBackground(color);
01000     paneContent.setName(name);
01001     paneContent.setVisible(true);
01002 
01003     JButton paneLabel = new JButton(name);
01004     paneLabel.setActionCommand(name);
01005     paneLabel.setBackground(color);
01006     paneLabel.setSize(100, 50);
01007     paneLabel.setVisible(true);
01008 
01009     DropTarget target1 = new DropTarget(paneLabel, DnDConstants.ACTION_MOVE,
01010         backendTransferListener);
01011     target1.setActive(true);
01012 
01013     DropTarget target2 = new DropTarget(paneContent, DnDConstants.ACTION_MOVE,
01014         backendTransferListener);
01015     target2.setActive(true);
01016 
01017     GridLayout iconLayout = (GridLayout) backendIcons.getLayout();
01018     iconLayout.setColumns(iconLayout.getColumns() + 1);
01019     GridLayout buttonsLayout = (GridLayout) backendButtons.getLayout();
01020     buttonsLayout.setColumns(buttonsLayout.getColumns() + 1);
01021     backendIcons.add(paneContent);
01022     backendButtons.add(paneLabel);
01023     // Adding to the main hashtable of states
01024     backendsState.put(name, paneContent);
01025   }
01026 
01027   /**
01028    * Load standard version for the panel
01029    * 
01030    * @param recoveryEnabled more options are available when recovery log is
01031    *          enabled for the database
01032    */
01033   public void actionLoadBackendPane(boolean recoveryEnabled)
01034   {
01035     // ////////////////////////////////////////////////////////////////////////
01036     // Define backend panel
01037     // /////////////////////////////////////////////////////////////////////////
01038     if (backendPanel == null)
01039     {
01040       backendPanel = new JPanel(new BorderLayout());
01041       backendPanel.setEnabled(true);
01042       backendPanel.setBackground(Color.white);
01043       backendPanel.setVisible(true);
01044     }
01045     else
01046     {
01047       backendPanel.remove(backendButtons);
01048       backendPanel.remove(backendIcons);
01049     }
01050 
01051     backendButtons = new JPanel(new GridLayout(1, 0));
01052     backendIcons = new JPanel(new GridLayout(1, 0));
01053     backendIcons.setBackground(Color.white);
01054     backendIcons.setVisible(true);
01055     backendButtons.setVisible(true);
01056 
01057     actionLoadBackendActionButton(GuiConstants.BACKEND_STATE_ENABLED);
01058     if (recoveryEnabled)
01059       actionLoadBackendActionButton(GuiConstants.BACKEND_STATE_RECOVERY);
01060     actionLoadBackendActionButton(GuiConstants.BACKEND_STATE_DISABLED);
01061     if (recoveryEnabled)
01062       actionLoadBackendActionButton(GuiConstants.BACKEND_STATE_BACKUP);
01063     if (recoveryEnabled)
01064       actionLoadBackendActionButton(GuiConstants.BACKEND_STATE_RESTORE);
01065     backendPanel.add(backendIcons, BorderLayout.CENTER);
01066     backendPanel.add(backendButtons, BorderLayout.NORTH);
01067 
01068     centerPane.validate();
01069     centerPane.repaint();
01070     validate();
01071     repaint();
01072   }
01073 
01074   /**
01075    * Load the virtual database after authentication.
01076    */
01077   public void publicActionLoadAuthenticatedDatabase()
01078   {
01079     loginFrame.setVisible(false);
01080     try
01081     {
01082       String databaseName = loginFrame.getDatabaseName();
01083       String login = loginFrame.getLoginBox().getText().trim();
01084       String password = loginFrame.getPasswordBox().getText().trim();
01085 
01086       VirtualDatabaseMBean mbean = null;
01087       try
01088       {
01089         mbean = currentJmxClient.getVirtualDatabaseProxy(databaseName, login,
01090             password);
01091         if (mbean == null)
01092           throw new IOException("MBean connection lost");
01093       }
01094       catch (IOException ioe)
01095       {
01096         appendDebugText(ioe.getMessage());
01097         actionUnloadBackends(currentJmxClient.getRemoteName());
01098         return;
01099       }
01100 
01101       if (!mbean.checkAdminAuthentication(login, password))
01102       {
01103         throw new Exception("Authentication failed");
01104       }
01105 
01106       databaseMBeans.put(databaseName, mbean);
01107       guiSession.addDatabaseToSession(databaseName, login, password);
01108 
01109       String[] list = mbean.viewControllerList();
01110       for (int i = 0; i < list.length; i++)
01111       {
01112         appendDebugText("Found controllerL" + list[i]);
01113         if (!guiSession.checkControllerInSession(list[i]))
01114         {
01115           actionLoadController(list[i]);
01116           RmiJmxClient client = (RmiJmxClient) jmxClients.get(list[i]);
01117           // get the listeners on the virtual database
01118           client.getVirtualDatabaseProxy(databaseName, login, password);
01119           paintControllerPane();
01120         }
01121       }
01122 
01123       boolean recoveryExist = mbean.hasRecoveryLog();
01124       appendDebugText("RecoveryLog is defined for this database:"
01125           + recoveryExist);
01126       actionLoadBackendPane(recoveryExist);
01127 
01128       publicActionLoadBackendsList(databaseName);
01129       actionLoadCheckpointNames(databaseName);
01130       publicActionLoadDumpList(databaseName);
01131     }
01132     catch (Exception e1)
01133     {
01134       appendDebugText("Could not connect to database", e1);
01135     }
01136   }
01137 
01138   /**
01139    * Quit the GUI
01140    */
01141   public void publicActionQuit()
01142   {
01143     try
01144     {
01145       guiSession.saveSessionToFile(new File(
01146           GuiConstants.CJDBC_DEFAULT_SESSION_FILE));
01147     }
01148     catch (IOException e)
01149     {
01150       System.out.println("Could not save session");
01151     }
01152     System.exit(0);
01153   }
01154 
01155   /**
01156    * Add a new driver to the controller. Start the file chooser and use the
01157    * proper MBean
01158    * 
01159    * @param controllerName name of the controller
01160    */
01161   public void publicActionLoadDriver(String controllerName)
01162   {
01163     if (jarFileChooser == null)
01164     {
01165       jarFileChooser = new JFileChooser(".");
01166       jarFileChooser.setFileFilter(new FileFilter()
01167       {
01168         /**
01169          * @see javax.swing.filechooser.FileFilter#accept(java.io.File)
01170          */
01171         public boolean accept(File f)
01172         {
01173           if (f.getAbsolutePath().endsWith(".jar") || f.isDirectory())
01174             return true;
01175           else
01176             return false;
01177         }
01178 
01179         /**
01180          * @see javax.swing.filechooser.FileFilter#getDescription()
01181          */
01182         public String getDescription()
01183         {
01184           return "Jar Files";
01185         }
01186       });
01187     }
01188     jarFileChooser.showOpenDialog(this);
01189     File selFile = jarFileChooser.getSelectedFile();
01190     try
01191     {
01192       if (selFile != null)
01193       {
01194         ControllerMBean controllerMBean = actionGetControllerBean(controllerName);
01195         controllerMBean.addDriver(readDriver(selFile.getAbsolutePath()));
01196       }
01197     }
01198     catch (Exception e)
01199     {
01200       appendDebugText("Could not load driver from jar file:"
01201           + selFile.getName());
01202     }
01203   }
01204 
01205   private byte[] readDriver(String filename) throws FileNotFoundException,
01206       IOException
01207   {
01208     File file;
01209     FileInputStream fileInput = null;
01210     file = new File(filename);
01211     fileInput = new FileInputStream(file);
01212 
01213     // Read the file into an array of bytes
01214     long size = file.length();
01215     if (size > Integer.MAX_VALUE)
01216       throw new IOException(ConsoleTranslate
01217           .get("controller.command.adddriver.file.too.big"));
01218     byte[] bytes = new byte[(int) size];
01219     int nb = fileInput.read(bytes);
01220     fileInput.close();
01221     if (nb != size)
01222       throw new IOException(ConsoleTranslate
01223           .get("controller.command.adddriver.file.not.read"));
01224     return bytes;
01225   }
01226 
01227   /**
01228    * Fetch the logs from the controller
01229    * 
01230    * @param controllerName the name of the controller
01231    */
01232   public void publicActionRefreshLogs(String controllerName)
01233   {
01234     try
01235     {
01236       ControllerMBean controllerMBean = actionGetControllerBean(controllerName);
01237       loggingTextPane.setText(controllerMBean.generateLogReport());
01238       appendDebugText("Re-Fetched logs for controller:" + controllerName);
01239     }
01240     catch (Exception e)
01241     {
01242       appendDebugText("Fail to fetch logs for controller:" + controllerName, e);
01243     }
01244   }
01245 
01246   /**
01247    * Clean the debug buffer
01248    */
01249   public void publicActionCleanDebugBuffer()
01250   {
01251     debugText = "";
01252     debugTextPane.setText("");
01253   }
01254 
01255   /**
01256    * saveConfigurationFile definition. Starts the JFile Chooser and write the
01257    * xml content to the selected file
01258    */
01259   public void publicActionSaveConfigurationFile()
01260   {
01261     try
01262     {
01263       if (saveFileChooser == null)
01264       {
01265         saveFileChooser = new JFileChooser();
01266         saveFileChooser.showSaveDialog(this);
01267         File selected = saveFileChooser.getSelectedFile();
01268         if (selected != null)
01269         {
01270           BufferedWriter writer = new BufferedWriter(new FileWriter(selected));
01271           writer.write(xmlTextPane.getText());
01272           writer.close();
01273         }
01274         else
01275         {
01276           appendDebugText("Did not select a file was saving...");
01277         }
01278       }
01279     }
01280     catch (Exception e)
01281     {
01282       appendDebugText("Error while writing to file:" + e.getMessage());
01283     }
01284   }
01285 
01286   /**
01287    * add a Controller to the list.
01288    */
01289   public void publicActionAddController()
01290   {
01291     newControllerFrame.setVisible(false);
01292     String ipAddress = newControllerFrame.getIpAddressBox().getText().trim();
01293     String port = newControllerFrame.getPortNumber().getText().trim();
01294     appendDebugText("Add controller with ip:" + ipAddress + " amd port:" + port);
01295     String name = ipAddress + ":" + port;
01296     if (guiSession.checkControllerInSession(name))
01297     {
01298       String message = GuiTranslate.get("error.controller.already.in.session");
01299       CJDBCException e = new CJDBCException(message);
01300       appendDebugText(message, e);
01301     }
01302     else
01303     {
01304       actionLoadController(name);
01305       paintControllerPane();
01306     }
01307   }
01308 
01309   /**
01310    * Load a new controller, the graphic object, the connection state and add it
01311    * to the controller pane list.
01312    * 
01313    * @param name the name(url) of the controller
01314    */
01315   private void actionLoadController(String name)
01316   {
01317     guiSession.addControllerToList(name);
01318     ControllerObject co = new ControllerObject(name);
01319     co.setActionCommand(GuiCommands.COMMAND_SELECT_CONTROLLER);
01320     co.addActionListener(guiActionListener);
01321     co.addMouseListener(new ControllerPopUpMenu(this, co));
01322     ControllerMBean controllerMBean = actionGetControllerBean(name);
01323     if (controllerMBean == null)
01324     {
01325       appendDebugText("Cannot load controller:" + name);
01326       return;
01327     }
01328     DropTarget target = new DropTarget(co, DnDConstants.ACTION_MOVE,
01329         configurationFileTransferListener);
01330     co.setDropTarget(target);
01331     appendDebugText("Loading controller:" + controllerMBean.getJmxName());
01332     if (currentJmxClient.isValidConnection())
01333     {
01334       co.setState(GuiConstants.CONTROLLER_STATE_UP);
01335     }
01336     else
01337     {
01338       co.setState(GuiConstants.CONTROLLER_STATE_DOWN);
01339     }
01340     actionAddObjectToGridLayout(controllerListPanel, co);
01341     controllerList.put(name, co);
01342   }
01343 
01344   /**
01345    * Action when a new controller has been selected
01346    * 
01347    * @param connectUrl the url of the controller that was selected
01348    */
01349   public void publicActionSelectNewController(String connectUrl)
01350   {
01351     Enumeration enume = controllerList.keys();
01352     String key = "";
01353     ControllerObject controller;
01354     while (enume.hasMoreElements())
01355     {
01356       key = (String) enume.nextElement();
01357       controller = (ControllerObject) controllerList.get(key);
01358       if (key.equalsIgnoreCase(connectUrl))
01359       {
01360         controller.setBorder(GuiConstants.TITLED_BORDER);
01361         controller.setBorderPainted(true);
01362       }
01363       else
01364         controller.setBorderPainted(false);
01365     }
01366     actionGetControllerBean(connectUrl);
01367     selectedController = connectUrl;
01368     actionLoadDatabaseList(connectUrl);
01369     publicActionLoadXmlController(connectUrl);
01370 
01371     if (selectedDatabase != null)
01372       publicActionLoadAuthenticatedDatabase();
01373 
01374     actionStartControllerLoggingThread(connectUrl);
01375   }
01376 
01377   /**
01378    * Returns the selectedController value.
01379    * 
01380    * @return Returns the selectedController.
01381    */
01382   public String getSelectedController()
01383   {
01384     return selectedController;
01385   }
01386 
01387   /**
01388    * Loads the graphic dump list for this databaser
01389    * 
01390    * @param databaseName the virtual database name
01391    */
01392   public void publicActionLoadDumpList(String databaseName)
01393   {
01394     VirtualDatabaseMBean databaseMBean = actionGetDatabaseBean(databaseName);
01395     try
01396     {
01397       File[] dumps = databaseMBean.getAvailableDumpFiles();
01398       appendDebugText("Loaded dumps for virtual database:" + databaseName);
01399       JPanel dumpPane = (JPanel) backendsState
01400           .get(GuiConstants.BACKEND_STATE_RESTORE);
01401       dumpPane.removeAll();
01402       for (int i = 0; i < dumps.length; i++)
01403       {
01404         appendDebugText("Adding dump:" + dumps[i]);
01405         DumpFileObject dfo = new DumpFileObject(dumps[i])
01406         {
01407           public JToolTip createToolTip()
01408           {
01409             return new JMultiLineToolTip();
01410           }
01411         };
01412         dfo.addMouseListener(new DumpPopUpMenu(this, databaseName, dfo));
01413         DropTarget target = new DropTarget(dfo, DnDConstants.ACTION_MOVE,
01414             backendTransferListener);
01415         dfo.setDropTarget(target);
01416         dumpPane.add(dfo);
01417       }
01418       paintBackendPane();
01419     }
01420     catch (Exception e)
01421     {
01422       e.printStackTrace();
01423       appendDebugText("Failed to load dumps for virtual database:"
01424           + databaseName + " because of:" + e.getMessage());
01425     }
01426   }
01427 
01428   /**
01429    * Load the xml for the given controller Gives the focus to the xml panel with
01430    * the new content
01431    * 
01432    * @param connectUrl controllerName
01433    */
01434   public void publicActionLoadXmlController(String connectUrl)
01435   {
01436     try
01437     {
01438       ControllerMBean controllerMBean = actionGetControllerBean(connectUrl);
01439       xmlTextPane.setText(controllerMBean.getXml());
01440       appendDebugText("Loaded xml configuration for controller:" + connectUrl);
01441     }
01442     catch (Exception e)
01443     {
01444       appendDebugText("Failed to get xml configuration for controller:"
01445           + connectUrl);
01446     }
01447   }
01448 
01449   /**
01450    * Select a new database action
01451    * 
01452    * @param value the name of the virtual dababase
01453    */
01454   public void publicActionSelectNewDatabase(String value)
01455   {
01456     selectedDatabase = value;
01457     try
01458     {
01459       VirtualDatabaseMBean databaseClient = actionGetDatabaseBean(value);
01460       if (databaseClient != null)
01461       {
01462         databaseClient.viewControllerList();
01463         publicActionLoadAuthenticatedDatabase();
01464       }
01465       Enumeration enume = databaseList.keys();
01466       String key = "";
01467       DatabaseObject database;
01468       while (enume.hasMoreElements())
01469       {
01470         key = (String) enume.nextElement();
01471         database = (DatabaseObject) databaseList.get(key);
01472         if (key.equalsIgnoreCase(value))
01473         {
01474           database.setBorder(GuiConstants.TITLED_BORDER);
01475           database.setBorderPainted(true);
01476         }
01477         else
01478           database.setBorderPainted(false);
01479       }
01480     }
01481     catch (Exception e)
01482     {
01483       appendDebugText("Failed to get access to database:" + value, e);
01484     }
01485   }
01486 
01487   /**
01488    * Load the xml configuration of the given database and display the xml buffer
01489    * 
01490    * @param databaseName virtual database name to get configuration from
01491    */
01492   public void publicActionLoadXmlDatabase(String databaseName)
01493   {
01494     try
01495     {
01496       VirtualDatabaseMBean databaseMBean = actionGetDatabaseBean(databaseName);
01497       xmlTextPane.setText(XmlTools.prettyXml(databaseMBean.getXml()));
01498       appendDebugText("Loaded xml configuration for database:" + databaseName);
01499       centerPane.setSelectedComponent(xmlScroll);
01500     }
01501     catch (Exception e)
01502     {
01503       appendDebugText("Failed to get xml configuration for database:"
01504           + databaseName, e);
01505     }
01506   }
01507 
01508   /**
01509    * Select a new configuration load the content of the xml file into the
01510    * xmlTextPane panel
01511    * 
01512    * @param file the path to the xml file
01513    */
01514   public void publicActionSelectNewConfigurationFile(String file)
01515   {
01516     try
01517     {
01518       xmlTextPane.setText(actionLoadXmlText(new File(file)));
01519       appendDebugText("Loaded xml configuration for file:" + file);
01520       centerPane.setSelectedComponent(xmlScroll);
01521     }
01522     catch (Exception e)
01523     {
01524       appendDebugText("Failed to load xml for file:" + file);
01525     }
01526   }
01527 
01528   /**
01529    * Send a shutdown command to the corresponding database
01530    * 
01531    * @param dob database object representing the database to shutdown
01532    * @param shutdownLevel the level to apply for the shutdown
01533    */
01534   public void publicActionShutdownDatabase(DatabaseObject dob, int shutdownLevel)
01535   {
01536     try
01537     {
01538       String databaseName = dob.getName();
01539       VirtualDatabaseMBean vdbMBean = actionGetDatabaseBean(databaseName);
01540       vdbMBean.shutdown(shutdownLevel);
01541       controllerListPanel.remove(dob);
01542       guiSession.getDatabaseItems().remove(databaseName);
01543       String controllerName = dob.getControllerName();
01544       actionUnloadBackends(controllerName);
01545       actionLoadDatabaseList(controllerName);
01546     }
01547     catch (Exception e)
01548     {
01549       appendDebugText("Failed to shutdown database", e);
01550     }
01551   }
01552 
01553   /**
01554    * Execute the backend drop action with this gui
01555    * 
01556    * @param backendName name of the backend
01557    * @param target the drop target used for the Dnd
01558    */
01559   public void publicActionExecuteBackendDrop(JButton target, String backendName)
01560   {
01561 
01562     String actionName = target.getActionCommand();
01563     if (actionName.equals(GuiConstants.BACKEND_STATE_RESTORE))
01564       publicActionRestoreBackend(backendName, ((DumpFileObject) target)
01565           .getDumpName());
01566     else
01567       publicActionExecuteBackendDrop(actionName, backendName);
01568   }
01569 
01570   private String actionDisplaySelectCheckpointFrame(String database)
01571   {
01572     VirtualDatabaseMBean databaseMBean = actionGetDatabaseBean(database);
01573     if (selectCheckpointFrame == null)
01574     {
01575       ArrayList list = databaseMBean.viewCheckpointNames();
01576       list.add(GuiConstants.BACKEND_NO_CHECKPOINT);
01577       String[] entries = (String[]) list.toArray(new String[list.size()]);
01578       selectCheckpointFrame = new GuiSelectCheckpointFrame(this, entries,
01579           guiActionListener);
01580       selectCheckpointFrame.setVisible(true);
01581     }
01582 
01583     JTextField field = selectCheckpointFrame.getValueField();
01584     selectCheckpointFrame = null;
01585     if (field == null)
01586       return null;
01587     String checkpoint = field.getText();
01588     return checkpoint;
01589   }
01590 
01591   /**
01592    * Check if the target column and the current state are the same
01593    * 
01594    * @param actionName the action from the DnD
01595    * @param backendName the name of the backend that is the target of the action
01596    * @return true if nothing has changed
01597    */
01598   private boolean isDropInSameColumn(String actionName, String backendName)
01599   {
01600     BackendObject bob = (BackendObject) backendList.get(backendName);
01601     String state = bob.getState();
01602     if (state.equalsIgnoreCase(actionName))
01603       return true;
01604     else
01605       return false;
01606   }
01607 
01608   /**
01609    * Execute the backend drop action with this gui
01610    * 
01611    * @param actionName action name on the backend
01612    * @param backendName the drop target used for the Dnd
01613    */
01614   public void publicActionExecuteBackendDrop(String actionName,
01615       String backendName)
01616   {
01617     appendDebugText("Got drop backend action:" + actionName + " from:"
01618         + backendName);
01619 
01620     BackendObject bob = (BackendObject) backendList.get(backendName);
01621     String database = bob.getDatabase();
01622     VirtualDatabaseMBean databaseMBean = actionGetDatabaseBean(bob
01623         .getDatabase());
01624 
01625     /*
01626      * This code does not do anything if
01627      * (actionName.equals(GuiConstants.BACKEND_STATE_RESTORE)) { ControllerMBean
01628      * controller = actionGetControllerBean(databaseMBean
01629      * .viewOwningController()); controller.listAvailableDumpFiles(); //
01630      * GuiSelectDumpFrame dump = new //
01631      * GuiSelectDumpFrame(this,,guiActionListener); }
01632      */
01633 
01634     if (isDropInSameColumn(actionName, backendName))
01635     {
01636       appendDebugText("Drop action is not relevant");
01637       return;
01638     }
01639 
01640     if (actionName.equals(GuiConstants.BACKEND_STATE_ENABLED))
01641     {
01642       try
01643       {
01644         DatabaseBackendMBean bean = bob.getMbean();
01645         String lastcheck = bean.getLastKnownCheckpoint();
01646         if (lastcheck != null)
01647         {
01648           actionSetBackendState(backendName,
01649               GuiConstants.BACKEND_STATE_RECOVERY);
01650           databaseMBean.enableBackendFromCheckpoint(backendName);
01651           return;
01652         }
01653         else
01654         {
01655           String checkpoint = actionDisplaySelectCheckpointFrame(database);
01656           if (checkpoint == null)
01657           {
01658             appendDebugText("Cancelling enable backend...");
01659             return;
01660           }
01661           appendDebugText("Using checkpoint:" + checkpoint
01662               + " to enable backend:" + backendName);
01663           if (checkpoint.equals(GuiConstants.BACKEND_NO_CHECKPOINT))
01664             databaseMBean.enableBackend(backendName);
01665           else
01666             databaseMBean.enableBackendFromCheckpoint(backendName);
01667         }
01668         // actionSetBackendState(backendName);
01669       }
01670       catch (Exception e)
01671       {
01672         appendDebugText("Failed to enable backend", e);
01673       }
01674     }
01675     else if (actionName.equals(GuiConstants.BACKEND_STATE_DISABLED))
01676     {
01677       try
01678       {
01679         // No recovery log defined.
01680         if (!databaseMBean.hasRecoveryLog())
01681           databaseMBean.disableBackend(backendName);
01682         else
01683         {
01684           String checkpoint = generateCheckpoint(backendName);
01685           //          
01686           // actionDisplaySelectCheckpointFrame(database);
01687           // if (checkpoint == null)
01688           // {
01689           // appendDebugText("Cancelling disable backend...");
01690           // return;
01691           // }
01692           appendDebugText("Using autogenerated checkpoint:" + checkpoint
01693               + " to disable backend:" + backendName);
01694           // if (checkpoint.equals(GuiConstants.BACKEND_NO_CHECKPOINT))
01695           // databaseMBean.disableBackend(backendName);
01696           // else
01697           databaseMBean.disableBackendWithCheckpoint(backendName, checkpoint);
01698         }
01699         actionSetBackendState(backendName);
01700       }
01701       catch (Exception e)
01702       {
01703         appendDebugText("Failed to disable backend", e);
01704       }
01705     }
01706     else if (actionName.equals(GuiConstants.BACKEND_STATE_NEW))
01707     {
01708       appendDebugText("Creating new backend from backend:" + bob.getName());
01709       publicActionNewBackendPrompt(bob);
01710     }
01711     else if (actionName.equals(GuiConstants.BACKEND_STATE_BACKUP))
01712     {
01713       publicActionBackupBackendPrompt(bob);
01714     }
01715 
01716     actionRefreshBackendState(bob);
01717   }
01718 
01719   private void actionRefreshBackendState(BackendObject bob)
01720   {
01721     String state = bob.getState();
01722     JPanel panel = (JPanel) backendsState.get(state);
01723     if (panel.getParent().equals(panel))
01724     {
01725       appendDebugText("refresh of backend:" + bob.getName() + " not needed");
01726     }
01727     else
01728     {
01729       appendDebugText("refresh of backend:" + bob.getName() + " needed");
01730       actionLoadBackend(bob.getDatabase(), bob.getName(), bob
01731           .getControllerName(), bob.isEnabled());
01732       // actionChangeBackendState(bob, bob.getState());
01733     }
01734   }
01735 
01736   /**
01737    * Generate a checkpoint name from the given backend and the current date.
01738    * 
01739    * @param backendName the backend to generate a checkpoint for
01740    * @return backend name concat date
01741    */
01742   private String generateCheckpoint(String backendName)
01743   {
01744     String check = backendName + ":"
01745         + new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date());
01746     return Strings.replace(check, ":", "-");
01747   }
01748 
01749   /**
01750    * Open the frame to fill in details to create a new backend
01751    * 
01752    * @param bob the backend to replicate
01753    */
01754   public void publicActionNewBackendPrompt(BackendObject bob)
01755   {
01756     if (newBackendFrame == null)
01757       newBackendFrame = new NewBackendFrame(bob, guiActionListener);
01758     else
01759       newBackendFrame.setBob(bob);
01760     newBackendFrame.setVisible(true);
01761   }
01762 
01763   /**
01764    * Restore a backend from a dump file
01765    * 
01766    * @param backendName name of the backend
01767    * @param dumpName name of the dump file
01768    */
01769   public void publicActionRestoreBackend(String backendName, String dumpName)
01770   {
01771     BackendObject bob = (BackendObject) backendList.get(backendName);
01772     try
01773     {
01774       if (bob.getMbean().isReadEnabled())
01775       {
01776         String message = "Cannot restore an enabled backend";
01777         appendDebugText(message, new ConsoleException(message));
01778         return;
01779       }
01780     }
01781     catch (Exception e)
01782     {
01783       appendDebugText(e.getMessage(), e);
01784       return;
01785     }
01786     appendDebugText("Restoring backend:" + backendName + " with dump name:"
01787         + dumpName);
01788 
01789     VirtualDatabaseMBean database = actionGetDatabaseBean(bob.getDatabase());
01790     new Thread(new RestoreBackendTask(this, database, bob, dumpName)).start();
01791   }
01792 
01793   /**
01794    * Execute a backup of the given backend
01795    * 
01796    * @param bob the backend object
01797    */
01798   public void publicActionBackupBackendPrompt(BackendObject bob)
01799   {
01800     String checkpoint = actionDisplayInputBackupFrame(bob.getDatabase(), bob
01801         .getName());
01802     if (checkpoint == null)
01803     {
01804       appendDebugText("No dump name received, cancelling action...");
01805       return;
01806     }
01807     VirtualDatabaseMBean database = actionGetDatabaseBean(bob.getDatabase());
01808     new Thread(new BackupBackendTask(this, database, bob, checkpoint)).start();
01809   }
01810 
01811   /**
01812    * Display the dump input frame
01813    * 
01814    * @param database virtual database to dump
01815    * @param backend backend to dump
01816    * @return dump name
01817    */
01818   private String actionDisplayInputBackupFrame(String database, String backend)
01819   {
01820     VirtualDatabaseMBean databaseMBean = actionGetDatabaseBean(database);
01821     if (inputBackupFrame == null)
01822     {
01823       File[] files = databaseMBean.getAvailableDumpFiles();
01824       int size = files.length;
01825       String[] entries = new String[size];
01826       for (int i = 0; i < size; i++)
01827       {
01828         entries[i] = files[i].getName();
01829       }
01830       inputBackupFrame = new GuiInputBackupFrame(this, entries,
01831           guiActionListener);
01832       inputBackupFrame.setValue(generateCheckpoint(backend));
01833       inputBackupFrame.setVisible(true);
01834     }
01835 
01836     JTextField field = inputBackupFrame.getValueField();
01837     inputBackupFrame = null;
01838     if (field == null)
01839       return null;
01840     String dump = field.getText();
01841     return dump;
01842   }
01843 
01844   /**
01845    * Set the cursor to be a hand
01846    */
01847   public void publicActionRefreshCursorShape()
01848   {
01849     appendDebugText("Refresh cursor for main frame");
01850     Cursor cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
01851     setCursor(cursor);
01852     backendPanel.setCursor(cursor);
01853     validate();
01854     repaint();
01855   }
01856 
01857   /**
01858    * Load a configuration file on a controller
01859    * 
01860    * @param filePath the configuration file
01861    * @param controllerName the name of the controller
01862    */
01863   public void publicActionExecuteControllerDrop(String filePath,
01864       String controllerName)
01865   {
01866     File file = new File(filePath);
01867     try
01868     {
01869       ControllerMBean controllerMBean = actionGetControllerBean(controllerName);
01870       controllerMBean.addVirtualDatabases(actionLoadXmlText(file));
01871       appendDebugText("Execute public action on controller drop for:"
01872           + filePath + " and:" + controllerName);
01873       actionLoadDatabaseList(controllerName);
01874     }
01875     catch (Exception e)
01876     {
01877       appendDebugText("Failed to load configuration file :" + file.getName(), e);
01878     }
01879   }
01880 
01881   /**
01882    * actionDatabaseDisableAll definition. Call the proper MBean to disable all
01883    * backends
01884    * 
01885    * @param databaseName virtual database name
01886    */
01887   public void publicActionDatabaseDisableAll(String databaseName)
01888   {
01889     try
01890     {
01891       actionGetDatabaseBean(databaseName).disableAllBackends();
01892       publicActionLoadBackendsList(databaseName);
01893       centerPane.setSelectedComponent(backendPanel);
01894       appendDebugText("Disable All backends for :" + databaseName
01895           + " was a success");
01896     }
01897     catch (Exception e)
01898     {
01899       appendDebugText("Disable All backends for :" + databaseName + " failed.",
01900           e);
01901     }
01902   }
01903 
01904   /**
01905    * GetInfo for the given controller
01906    * 
01907    * @param controllerName the controllerName
01908    */
01909   public void publicActionGetControllerInfo(String controllerName)
01910   {
01911     try
01912     {
01913       ControllerMBean controllerMBean = actionGetControllerBean(controllerName);
01914       infoTextPane.setText(controllerMBean.getXml());
01915       centerPane.setSelectedComponent(infoScroll);
01916     }
01917     catch (Exception e)
01918     {
01919       appendDebugText("Failed to get info for controller:" + controllerName, e);
01920     }
01921   }
01922 
01923   /**
01924    * Shutdown the given controller
01925    * 
01926    * @param controllerName name of the controller to shutdown
01927    */
01928   public void publicActionShutdownController(String controllerName)
01929   {
01930     ControllerMBean controllerMBean = null;
01931     int shutdownLevel = 2;
01932     try
01933     {
01934       controllerMBean = actionGetControllerBean(controllerName);
01935     }
01936     catch (Exception e)
01937     {
01938       appendDebugText("Failed to get a proxy to shutdown the controller:"
01939           + controllerName, e);
01940     }
01941     try
01942     {
01943       if (controllerMBean != null)
01944       {
01945         ArrayList databases = controllerMBean.getVirtualDatabaseNames();
01946         for (int i = 0; i < databases.size(); i++)
01947         {
01948           DatabaseObject dob = (DatabaseObject) databaseList.get(databases
01949               .get(i));
01950           appendDebugText("Shutting down database:" + dob.getName()
01951               + " with level:" + shutdownLevel);
01952           publicActionShutdownDatabase(dob, shutdownLevel);
01953         }
01954         controllerMBean.shutdown(shutdownLevel);
01955       }
01956       else
01957         appendDebugText("Failed to get a proxy to shutdown the controller:"
01958             + controllerName);
01959     }
01960     catch (Exception e)
01961     {
01962       // lost connection expected
01963     }
01964     publicActionLoadControllerList();
01965 
01966   }
01967 
01968   /**
01969    * Get a report for the given controller
01970    * 
01971    * @param controllerName the controller to get the report from
01972    */
01973   public void publicActionControllerReport(String controllerName)
01974   {
01975     try
01976     {
01977       ControllerMBean controllerMBean = actionGetControllerBean(controllerName);
01978       infoTextPane.setText(controllerMBean.generateReport());
01979       centerPane.setSelectedComponent(infoScroll);
01980     }
01981     catch (Exception e)
01982     {
01983       appendDebugText("Failed to get info for controller:" + controllerName, e);
01984     }
01985   }
01986 
01987   /**
01988    * Delete a dump of a database from the virtual database
01989    * 
01990    * @param databaseName the url of the controller
01991    * @param dump the dump object
01992    */
01993   public void publicActionDeleteDump(String databaseName, DumpFileObject dump)
01994   {
01995     boolean confirm = actionDisplayConfirmFrame(GuiTranslate
01996         .get("gui.confirm.delete.dump"));
01997     if (!confirm)
01998     {
01999       appendDebugText("Action is not confirmed, cancelling deletion");
02000       return;
02001     }
02002     VirtualDatabaseMBean database = actionGetDatabaseBean(databaseName);
02003     try
02004     {
02005       database.removeDumpFile(dump.getDumpFile());
02006       appendDebugText("Removed dump file:" + dump.getDumpFile().getName()
02007           + " from controller:" + databaseName);
02008       publicActionLoadDumpList(databaseName);
02009     }
02010     catch (Exception e)
02011     {
02012       appendDebugText("Failed to removed dump file:"
02013           + dump.getDumpFile().getName() + " from controller:" + databaseName,
02014           e);
02015     }
02016   }
02017 
02018   /**
02019    * Display frame to confirm action
02020    * 
02021    * @param message message to confirm
02022    * @return true if YES is selected, false otherwise
02023    */
02024   private boolean actionDisplayConfirmFrame(String message)
02025   {
02026     int value = JOptionPane.showConfirmDialog(this, message, message,
02027         JOptionPane.YES_NO_OPTION);
02028     if (value == JOptionPane.YES_OPTION)
02029       return true;
02030     else
02031       return false;
02032   }
02033 
02034   /**
02035    * Execute the backend drop action with this gui
02036    * 
02037    * @param panel the target of the drop
02038    * @param backendName name of the backend that is the target of the drop
02039    */
02040   public void publicActionExecuteBackendDrop(JPanel panel, String backendName)
02041   {
02042     publicActionExecuteBackendDrop(panel.getName(), backendName);
02043   }
02044 
02045   /**
02046    * Load the controller log4j configuration file in the info buffer
02047    * 
02048    * @param controllerName the controller's url
02049    */
02050   public void publicActionControllerLogConfiguration(String controllerName)
02051   {
02052     try
02053     {
02054       ControllerMBean controllerMBean = actionGetControllerBean(controllerName);
02055       logConfigTextPane.setText(controllerMBean.viewLogConfigurationFile());
02056       centerPane.setSelectedComponent(logConfigScroll);
02057       logConfigTextPane.addMouseListener(new LogEditPopUpMenu(this,
02058           controllerName, logConfigTextPane));
02059     }
02060     catch (Exception e)
02061     {
02062       appendDebugText("Failed to get log4j configuration for controller:"
02063           + controllerName, e);
02064     }
02065   }
02066 
02067   /**
02068    * Update the controller log4j configuration file, and restart the logger
02069    * thread
02070    * 
02071    * @param controllerName the controller's url
02072    * @param newContent the new log4j configuration
02073    */
02074   public void publicActionUpdateControllerLogConfiguration(
02075       String controllerName, String newContent)
02076   {
02077     try
02078     {
02079       appendDebugText("Updating log4j configuration for controller:"
02080           + controllerName);
02081       ControllerMBean controllerMBean = actionGetControllerBean(controllerName);
02082       controllerMBean.updateLogConfigurationFile(newContent);
02083       actionStartControllerLoggingThread(controllerName);
02084     }
02085     catch (Exception e)
02086     {
02087       appendDebugText("Failed to update log4j configuration for controller:"
02088           + controllerName, e);
02089     }
02090   }
02091 
02092   /**
02093    * Change the log4j configuration to Debug mode for all loggers
02094    * 
02095    * @param controllerName the name of the controller of this configuration
02096    * @param logConfiguration the content as a <code>String</code> of the log4j
02097    *          configuration
02098    */
02099   public void publicActionSetLogConfigurationDebug(String controllerName,
02100       String logConfiguration)
02101   {
02102     try
02103     {
02104       String newContent = actionReplaceInConfiguration(logConfiguration,
02105           "INFO", "DEBUG");
02106       publicActionUpdateControllerLogConfiguration(controllerName, newContent);
02107     }
02108     catch (Exception e)
02109     {
02110       appendDebugText("Setting log configation to debug failed for controller:"
02111           + controllerName, e);
02112     }
02113   }
02114 
02115   /**
02116    * Add/remove log4j server output
02117    * 
02118    * @param enableServer <tt>true</tt> to enable
02119    * @param controllerName of the controller for this configuration
02120    * @param logConfiguration logFile name
02121    */
02122   public void publicActionSetLogConfigurationServer(boolean enableServer,
02123       String controllerName, String logConfiguration)
02124   {
02125     try
02126     {
02127       String msg = "Setting server configuration to " + enableServer
02128           + " for controller:" + controllerName;
02129       appendDebugText(msg);
02130       String newContent = "";
02131       if (enableServer)
02132       {
02133         // if it was enabled before ?
02134         String tmp = actionReplaceInConfiguration(logConfiguration,
02135             "Console,server", "Console");
02136         newContent = actionReplaceInConfiguration(tmp, "Console,",
02137             "Console,server,");
02138       }
02139       else
02140       {
02141         newContent = actionReplaceInConfiguration(logConfiguration,
02142             "Console,server", "Console");
02143       }
02144       publicActionUpdateControllerLogConfiguration(controllerName, newContent);
02145     }
02146     catch (Exception e)
02147     {
02148       appendDebugText(
02149           "Setting log configation of appender server failed for controller:"
02150               + controllerName, e);
02151     }
02152 
02153   }
02154 
02155   private String actionReplaceInConfiguration(String logConfiguration,
02156       String oldMode, String newMode) throws IOException
02157   {
02158     BufferedReader reader = new BufferedReader(new StringReader(
02159         logConfiguration));
02160     StringBuffer buffer = new StringBuffer();
02161     String line;
02162     int index = 0;
02163     while ((line = reader.readLine()) != null)
02164     {
02165       while ((index = line.indexOf(oldMode, index + 1)) != -1)
02166       {
02167         line = line.substring(0, index) + newMode
02168             + line.substring(index + oldMode.length());
02169       }
02170       buffer.append(line + System.getProperty("line.separator"));
02171     }
02172     logConfigTextPane.setText(buffer.toString());
02173     return buffer.toString();
02174   }
02175 
02176   /**
02177    * Change the log4j configuration to Info mode for all loggers
02178    * 
02179    * @param controllerName the name of the controller of this configuration
02180    * @param logConfiguration the content as a <code>String</code> of the log4j
02181    *          configuration
02182    */
02183   public void publicActionSetLogConfigurationInfo(String controllerName,
02184       String logConfiguration)
02185   {
02186     try
02187     {
02188       String newContent = actionReplaceInConfiguration(logConfiguration,
02189           "DEBUG", "INFO");
02190       publicActionUpdateControllerLogConfiguration(controllerName, newContent);
02191     }
02192     catch (Exception e)
02193     {
02194       appendDebugText("Setting log configation to debug failed for controller:"
02195           + controllerName, e);
02196     }
02197 
02198   }
02199 
02200   /**
02201    * Returns the backendList value.
02202    * 
02203    * @return Returns the backendList.
02204    */
02205   public Hashtable getBackendList()
02206   {
02207     return backendList;
02208   }
02209 
02210   /**
02211    * Clean the content of the logging text pane and repaint
02212    */
02213   public void publicActioncleanLoggingPane()
02214   {
02215     loggingTextPane.setText("");
02216     loggingTextPane.validate();
02217     loggingTextPane.repaint();
02218   }
02219 
02220   /**
02221    * Remove a configuration file from the list
02222    * 
02223    * @param cfo the file object associated
02224    */
02225   public void publicActionRemoveConfigurationFile(ConfigurationFileObject cfo)
02226   {
02227     Container container = cfo.getParent();
02228     container.remove(cfo);
02229     System.out.println(guiSession.getConfigurationFiles().remove(
02230         new File(cfo.getFilePath())));
02231     container.validate();
02232     container.repaint();
02233   }
02234 
02235   /**
02236    * Removes a controller from the gui
02237    * 
02238    * @param controllerName the name of the controller
02239    */
02240   public void publicActionControllerRemove(String controllerName)
02241   {
02242     ControllerObject co = (ControllerObject) controllerList
02243         .remove(controllerName);
02244     if (co != null)
02245     {
02246       controllerListPanel.remove(co);
02247       controllerListPanel.validate();
02248       controllerListPanel.repaint();
02249     }
02250     guiSession.getControllerItems().remove(controllerName);
02251   }
02252 
02253   /**
02254    * Start monitoring console.
02255    * 
02256    * @param controllerName the controller to monitor
02257    * @param displayController true if controller pane should be displayed
02258    * @param displayVdb true if virtual database pane should be displayed
02259    * @param displayBackends true if backend pane should be displayed
02260    */
02261   public void publicActionStartMonitor(String controllerName,
02262       boolean displayController, boolean displayVdb, boolean displayBackends)
02263   {
02264     appendDebugText("Creating monitoring console for controller:"
02265         + controllerName);
02266     try
02267     {
02268       new MonitoringConsole(controllerName, displayController
02269           ? actionGetControllerBean(controllerName)
02270           : null, displayVdb ? actionGetDatabaseBean(selectedDatabase) : null,
02271           displayBackends);
02272     }
02273     catch (Exception e)
02274     {
02275       appendDebugText("Loading of monitoring console failed for controller:"
02276           + controllerName, e);
02277     }
02278   }
02279 
02280   /**
02281    * Create the new backend by sending the jmx command
02282    */
02283   public void publicActionCreateBackendExecute()
02284   {
02285     newBackendFrame.setVisible(false);
02286     BackendObject bob = newBackendFrame.getBob();
02287     VirtualDatabaseMBean database = actionGetDatabaseBean(bob.getDatabase());
02288     String oldname = bob.getName();
02289     String newname = newBackendFrame.getNewName().getText();
02290     String url = newBackendFrame.getNewUrl().getText();
02291     HashMap map = new HashMap();
02292     map.put("url", url);
02293     try
02294     {
02295       database.replicateBackend(oldname, newname, map);
02296     }
02297     catch (Exception e)
02298     {
02299       appendDebugText("Failed to create new backend:" + newname, e);
02300     }
02301   }
02302 
02303   /**
02304    * Display the cache content in a new frame
02305    * 
02306    * @param databaseName database name that contains the cache
02307    */
02308   public void publicActionViewCache(String databaseName)
02309   {
02310     try
02311     {
02312       DataCollectorMBean collector = currentJmxClient.getDataCollectorProxy();
02313       CacheViewer viewer = new CacheViewer(collector
02314           .retrieveCacheData(databaseName));
02315       viewer.display();
02316     }
02317     catch (Exception e)
02318     {
02319       appendDebugText("Failed to collect cache data for database:"
02320           + databaseName, e);
02321     }
02322   }
02323 
02324   /**
02325    * Display the SQL stats
02326    * 
02327    * @param databaseName virtual database name
02328    */
02329   public void publicActionViewSQLStats(String databaseName)
02330   {
02331     try
02332     {
02333       DataCollectorMBean collector = currentJmxClient.getDataCollectorProxy();
02334       SQLStatViewer viewer = new SQLStatViewer(collector
02335           .retrieveSQLStats(databaseName));
02336       viewer.display();
02337     }
02338     catch (Exception e)
02339     {
02340       appendDebugText(
02341           "Failed to collect sql data for database:" + databaseName, e);
02342     }
02343 
02344   }
02345 
02346   /**
02347    * Display the cache stats
02348    * 
02349    * @param databaseName virtual database name
02350    */
02351   public void publicActionViewCacheStats(String databaseName)
02352   {
02353     try
02354     {
02355       DataCollectorMBean collector = currentJmxClient.getDataCollectorProxy();
02356       CacheStatsViewer viewer = new CacheStatsViewer(collector
02357           .retrieveCacheStatsData(databaseName));
02358       viewer.display();
02359     }
02360     catch (Exception e)
02361     {
02362       appendDebugText("Failed to collect cache stats for database:"
02363           + databaseName, e);
02364     }
02365   }
02366 
02367   /**
02368    * Get the action listener for the gui
02369    * 
02370    * @return the listener of events
02371    */
02372   public CjdbcGuiListener getGuiActionListener()
02373   {
02374     return guiActionListener;
02375   }
02376 
02377   /**
02378    * Returns the guiSession value.
02379    * 
02380    * @return Returns the guiSession.
02381    */
02382   public GuiSession getGuiSession()
02383   {
02384     return guiSession;
02385   }
02386 
02387   /**
02388    * Returns the jmxClients value.
02389    * 
02390    * @return Returns the jmxClients.
02391    */
02392   public Hashtable getJmxClients()
02393   {
02394     return jmxClients;
02395   }
02396 
02397   /**
02398    * Remove the backend graphic object from the gui
02399    * 
02400    * @param backendName the backend to remove
02401    */
02402   public void publicActionRemoveBackendFromGui(String backendName)
02403   {
02404     BackendObject bo = (BackendObject) backendList.remove(backendName);
02405     if (bo != null)
02406     {
02407       backendIcons.remove(bo);
02408       JPanel panel = (JPanel) backendsState.get(bo.getState());
02409       panel.remove(bo);
02410       paintBackendPane();
02411     }
02412   }
02413 
02414   /**
02415    * Remove a backend from the backend list, and from the controller
02416    * 
02417    * @param bo the <code>BackendObject</code> that originated the action
02418    */
02419   public void publicActionRemoveBackend(BackendObject bo)
02420   {
02421     boolean confirm = actionDisplayConfirmFrame(GuiTranslate.get(
02422         "gui.confirm.remove.backend", bo.getName()));
02423     if (!confirm)
02424     {
02425       appendDebugText("Cancelling backend deletion...");
02426       return;
02427     }
02428 
02429     String controllerName = bo.getControllerName();
02430     String databaseName = bo.getDatabase();
02431     String backendName = bo.getName();
02432     RmiJmxClient jmxClient = (RmiJmxClient) jmxClients.get(controllerName);
02433     String user = guiSession.getAuthenticatedDatabaseLogin(databaseName);
02434     String password = guiSession.getAuthenticatedDatabasePassword(databaseName);
02435     try
02436     {
02437       VirtualDatabaseMBean mbean = jmxClient.getVirtualDatabaseProxy(
02438           databaseName, user, password);
02439       mbean.removeBackend(backendName);
02440       publicActionRemoveBackendFromGui(backendName);
02441     }
02442     catch (Exception e)
02443     {
02444       appendDebugText("Cannot remove backend:" + backendName, e);
02445     }
02446 
02447   }
02448 
02449   /**
02450    * Execute a backend transfer from one controller to an other one
02451    * 
02452    * @param backendName the name of the backend to transfer
02453    * @param controllerName the target controller to transfer to
02454    */
02455   public void publicActionExecuteTransfer(String backendName,
02456       String controllerName)
02457   {
02458     BackendObject bo = (BackendObject) backendList.get(backendName);
02459     String controllerNameOrigin = bo.getControllerName();
02460     RmiJmxClient jmxClient = (RmiJmxClient) jmxClients
02461         .get(controllerNameOrigin);
02462     String databaseName = bo.getDatabase();
02463     String user = guiSession.getAuthenticatedDatabaseLogin(databaseName);
02464     String password = guiSession.getAuthenticatedDatabasePassword(databaseName);
02465     try
02466     {
02467       VirtualDatabaseMBean mbean = jmxClient.getVirtualDatabaseProxy(
02468           databaseName, user, password);
02469       mbean.transferBackend(backendName, controllerName);
02470       bo.setControllerName(controllerName);
02471       // publicActionRemoveBackendFromGui(backendName);
02472     }
02473     catch (Exception e)
02474     {
02475       appendDebugText("Cannot remove backend:" + backendName, e);
02476     }
02477   }
02478 
02479   /**
02480    * Performs checks before calling <method>publicActionRemoveBackendFromGui
02481    * </method>
02482    * 
02483    * @param backendName the backend name to remove
02484    * @param controller the controller that it was removed from
02485    */
02486   public void publicActionRemoveBackendFromGui(String backendName,
02487       String controller)
02488   {
02489     BackendObject bo = (BackendObject) backendList.get(backendName);
02490     if (bo != null)
02491     {
02492       String boController = bo.getControllerName();
02493       if (boController.equals(controller))
02494         publicActionRemoveBackendFromGui(backendName);
02495       else
02496       {
02497         appendDebugText("Call for removing backend:" + backendName
02498             + " from controller:" + controller
02499             + " but backend is on controller:" + boController);
02500       }
02501     }
02502 
02503   }
02504 
02505   /**
02506    * Display the shutdown dialog and then shutdown the database with the
02507    * corresponding level
02508    * 
02509    * @param database the database name we want to shutdown.
02510    */
02511   public void publicActionDisplayShutdownFrame(DatabaseObject database)
02512   {
02513     if (selectShutdownFrame == null)
02514     {
02515       selectShutdownFrame = new GuiSelectShutdownFrame(this, guiActionListener);
02516       selectShutdownFrame.setVisible(true);
02517     }
02518     String shutdownLevel = selectShutdownFrame.getValueField().getText();
02519     // Defaults to safe mode
02520     int iLevel = Constants.SHUTDOWN_SAFE;
02521     if (shutdownLevel.equals(GuiCommands.COMMAND_SHUTDOWN_SAFE))
02522       iLevel = Constants.SHUTDOWN_SAFE;
02523     else if (shutdownLevel.equals(GuiCommands.COMMAND_SHUTDOWN_FORCE))
02524       iLevel = Constants.SHUTDOWN_FORCE;
02525     else if (shutdownLevel.equals(GuiCommands.COMMAND_SHUTDOWN_WAIT))
02526       iLevel = Constants.SHUTDOWN_WAIT;
02527     appendDebugText("shudown level of database:" + database.getName() + " is:"
02528         + shutdownLevel);
02529     selectShutdownFrame = null;
02530     publicActionShutdownDatabase(database, iLevel);
02531   }
02532 
02533   /**
02534    * Display the content of the recovery log in a frame
02535    * 
02536    * @param databaseName the database that containts the recovery log we want
02537    */
02538   public void publicActionViewRecoveryLog(String databaseName)
02539   {
02540     try
02541     {
02542       DataCollectorMBean collector = currentJmxClient.getDataCollectorProxy();
02543       RecoveryLogViewer viewer = new RecoveryLogViewer(collector
02544           .retrieveRecoveryLogData(databaseName));
02545       viewer.display();
02546     }
02547     catch (Exception e)
02548     {
02549       appendDebugText("Failed to collect cache stats for database:"
02550           + databaseName, e);
02551     }
02552   }
02553 
02554   /**
02555    * Set the checkpoint of a backend
02556    * 
02557    * @param bo the backend to change the checkpoint
02558    */
02559   public void publicActionSetCheckpoint(BackendObject bo)
02560   {
02561     String backendName = bo.getName();
02562     String database = bo.getDatabase();
02563     String checkpoint = actionDisplaySelectCheckpointFrame(database);
02564     try
02565     {
02566       appendDebugText("Setting checkpoint for backend:" + backendName + ":"
02567           + checkpoint);
02568       bo.getMbean().setLastKnownCheckpoint(checkpoint);
02569     }
02570     catch (Exception e)
02571     {
02572       appendDebugText("Failed to set checkpoint for backend:" + backendName, e);
02573     }
02574   }
02575 
02576   /**
02577    * Unset checkpoint of a backend (set it to null)
02578    * 
02579    * @param bo backend object
02580    */
02581   public void publicActionUnSetCheckpoint(BackendObject bo)
02582   {
02583     String backendName = bo.getName();
02584     boolean confirm = actionDisplayConfirmFrame(GuiTranslate.get(
02585         "gui.confirm.unset.backend.checkpoint", backendName));
02586     if (!confirm)
02587     {
02588       appendDebugText("Cancelling backend null checkpoint...");
02589       return;
02590     }
02591     try
02592     {
02593       appendDebugText("UnSetting checkpoint for backend:" + backendName);
02594       bo.getMbean().setLastKnownCheckpoint(null);
02595     }
02596     catch (Exception e)
02597     {
02598       appendDebugText("Failed to unset checkpoint for backend:" + backendName,
02599           e);
02600     }
02601     finally
02602     {
02603       actionRefreshBackendState(bo);
02604     }
02605 
02606   }
02607 
02608   /**
02609    * Test jdbc connection on this backend
02610    * 
02611    * @param bo the backend object to test the connection on
02612    */
02613   public void publicActionTestBackendConnection(BackendObject bo)
02614   {
02615     try
02616     {
02617       DatabaseBackendMBean bean = bo.getMbean();
02618       boolean ok = bean.isJDBCConnected();
02619       String message = "Backend " + bo.getName();
02620       if (ok)
02621         message += " has ";
02622       else
02623         message += " does not have ";
02624       message += "JDBC Connectivity.";
02625 
02626       appendDebugText("Result of JDBC Connect[" + bo.getName() + "]:" + ok);
02627 
02628       Icon icon = (ok)
02629           ? GuiIcons.BACKEND_ENABLED_ICON
02630           : GuiIcons.BACKEND_DISABLED_ICON;
02631       JOptionPane.showMessageDialog(this, message, bo.getName(),
02632           JOptionPane.INFORMATION_MESSAGE, icon);
02633     }
02634     catch (Exception e)
02635     {
02636       appendDebugText(
02637           "Cannot determine if backend has still JDBC connectivity", e);
02638     }
02639   }
02640 
02641   /**
02642    * Refresh the list of mbeans
02643    */
02644   public void publicActionRefreshMBeans()
02645   {
02646     Set set;
02647     if (currentJmxClient == null)
02648     {
02649       appendDebugText("Jmx Client has not been set yet");
02650       return;
02651     }
02652     try
02653     {
02654       appendDebugText("Refreshing mbeans for jmx server:"
02655           + currentJmxClient.getRemoteName());
02656       set = currentJmxClient.listCJDBCMBeans();
02657       int size = set.size();
02658       Iterator iter = set.iterator();
02659       Object[] data = new Object[size];
02660       for (int i = 0; i < size; i++)
02661         data[i] = ((ObjectInstance) iter.next()).getObjectName();
02662       mbeanList.setListData(data);
02663       mbeanList.validate();
02664       appendDebugText("Finished Refreshing mbeans for jmx server:"
02665           + currentJmxClient.getRemoteName());
02666     }
02667     catch (Exception e)
02668     {
02669       appendDebugText("Failed Refreshing mbeans for jmx server:"
02670           + currentJmxClient.getRemoteName());
02671     }
02672   }
02673 
02674   /**
02675    * Position the jmx frames on the desktop
02676    * 
02677    * @param vertical tile the frames vertically if true, horizontally if false
02678    */
02679   public void publicActionTileJmxFrames(boolean vertical)
02680   {
02681     Dimension dim = jmxPanel.getSize();
02682     double height = dim.getHeight();
02683     double width = dim.getWidth();
02684     if (vertical)
02685       width = width / 3;
02686     else
02687       height = height / 3;
02688 
02689     Dimension newDim = new Dimension((int) width, (int) height);
02690     attributeFrame.setSize(newDim);
02691     operationFrame.setSize(newDim);
02692     mbeanFrame.setSize(newDim);
02693 
02694     int x = (int) jmxPanel.getLocation().getX();
02695     int y = 0; // problem with y value
02696 
02697     mbeanFrame.setLocation(x, y);
02698     if (vertical)
02699     {
02700       mbeanFrame.setLocation(x, y);
02701       attributeFrame.setLocation((int) (x + width), y);
02702       operationFrame.setLocation((int) (x + 2 * width), y);
02703     }
02704     else
02705     {
02706       mbeanFrame.setLocation(x, y);
02707       attributeFrame.setLocation(x, (int) (y + height));
02708       operationFrame.setLocation(x, (int) (y + 2 * height));
02709     }
02710 
02711     jmxPanel.validate();
02712 
02713   }
02714 
02715   /**
02716    * Refresh MBean attributes.
02717    * 
02718    * @param mbean the MBean to refresh
02719    */
02720   public void publicActionRefreshMBeanAttributes(ObjectName mbean)
02721   {
02722     try
02723     {
02724       appendDebugText("Fetching attributes for mbean:" + mbean);
02725       MBeanInfo info = currentJmxClient.getMBeanInfo(mbean);
02726       MBeanAttributeInfo[] attrInfo = info.getAttributes();
02727 
02728       AttributeModel dataModel = new AttributeModel(attrInfo, currentJmxClient,
02729           mbean);
02730       attributeTable.setModel(dataModel);
02731     }
02732     catch (Exception e)
02733     {
02734       appendDebugText("Could not fetch attributes for mbean:" + mbean);
02735     }
02736   }
02737 
02738   /**
02739    * Refresh MBean methods.
02740    * 
02741    * @param mbean the MBean to refresh
02742    */
02743   public void publicActionRefreshMBeanMethods(ObjectName mbean)
02744   {
02745     try
02746     {
02747       appendDebugText("Fetching methods for mbean:" + mbean);
02748       MBeanInfo info = currentJmxClient.getMBeanInfo(mbean);
02749       MBeanOperationInfo[] operInfo = info.getOperations();
02750 
02751       OperationModel dataModel = new OperationModel(operInfo);
02752       operationTable.setModel(dataModel);
02753     }
02754     catch (Exception e)
02755     {
02756       appendDebugText("Could not fetch methods for mbean:" + mbean);
02757     }
02758   }
02759 
02760   /**
02761    * Returns the currentJmxClient value.
02762    * 
02763    * @return Returns the currentJmxClient.
02764    */
02765   public RmiJmxClient getCurrentJmxClient()
02766   {
02767     return currentJmxClient;
02768   }
02769 
02770   /**
02771    * Sets the currentJmxClient value.
02772    * 
02773    * @param currentJmxClient The currentJmxClient to set.
02774    */
02775   public void setCurrentJmxClient(RmiJmxClient currentJmxClient)
02776   {
02777     this.currentJmxClient = currentJmxClient;
02778   }
02779 
02780   /**
02781    * Opens a window to perform a jmx operation
02782    * 
02783    * @param info an <code>MBeanOperationInfo</code> object
02784    * @param name name of the JMX object
02785    */
02786   public void getOperationCallDialog(ObjectName name, MBeanOperationInfo info)
02787   {
02788     new OperationCallDialog(this, name, info).setVisible(true);
02789   }
02790 
02791   /**
02792    * Opens a window t ochange an attribute
02793    * 
02794    * @param info an <code>MBeanOperationInfo</code> object
02795    * @param name name of the JMX object
02796    */
02797   public void getAttributeChangeDialog(ObjectName name, MBeanAttributeInfo info)
02798   {
02799     new AttributeChangeDialog(this, name, info).setVisible(true);
02800   }
02801 
02802 }

Generated on Mon Apr 11 22:01:30 2005 for C-JDBC by  doxygen 1.3.9.1