/* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2002 * Copyright by ESO (in the framework of the ALMA collaboration) * and Cosylab 2002, All rights reserved * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package com.cosylab.logging; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.Insets; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowEvent; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JRootPane; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JViewport; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; import org.omg.CORBA.ORB; import alma.acs.container.AdvancedContainerServices; import alma.acs.container.ContainerServicesBase; import alma.acs.gui.widgets.ExtendedTextArea; import alma.acs.logging.archive.ArchiveConnectionManager; import alma.acs.logging.archive.ArchiveConnectionManager.DBState; import alma.acs.logging.archive.QueryDlg; import alma.acs.logging.archive.zoom.ManualZoomDlg; import alma.acs.logging.archive.zoom.ZoomManager; import alma.acs.logging.archive.zoom.ZoomPrefsDlg; import alma.acs.logging.dialogs.error.ErrorLogDialog; import alma.acs.logging.dialogs.main.LogFrame; import alma.acs.logging.dialogs.main.LogMenuBar; import alma.acs.logging.dialogs.main.LogNavigationBar; import alma.acs.logging.dialogs.main.LogToolBar; import alma.acs.logging.errorbrowser.ErrorBrowserDlg; import alma.acs.logging.preferences.ExpertPrefsDlg; import alma.acs.logging.preferences.UserPreferences; import alma.acs.logging.table.LogEntryTable; import alma.acs.logging.table.LogTableDataModel; import com.cosylab.logging.MessageWidget.MessageType; import com.cosylab.logging.MessageWidget.MessageWidgetListener; import com.cosylab.logging.client.DetailedLogTable; import com.cosylab.logging.engine.Filterable; import com.cosylab.logging.engine.FiltersVector; import com.cosylab.logging.engine.ACS.ACSLogConnectionListener; import com.cosylab.logging.engine.ACS.ACSRemoteErrorListener; import com.cosylab.logging.engine.ACS.ACSRemoteLogListener; import com.cosylab.logging.engine.ACS.LCEngine; import com.cosylab.logging.engine.audience.Audience.AudienceInfo; import com.cosylab.logging.engine.log.ILogEntry; import com.cosylab.logging.engine.log.LogTypeHelper; import com.cosylab.logging.search.SearchDialog; import com.cosylab.logging.settings.FilterChooserDialog; import com.cosylab.logging.stats.StatsDlg; import com.cosylab.logging.viewcoordination.ViewCoordinator; /** * Defines a JRootPane Application LoggingClient for displaying event logs * received through the CORBA protocol for the purpose of monitoring and * reviewing of the logs. It contains of a JScrollPane scrollLogTable for the * logs and a LogEntryTable logEntryTable for displaying the status * as well as a JPanel ivjJFrameContentPane. Multiple listeners handle * user's input. * Based on the current code and our understanding of it one could describe * the information flow as follows. User's input triggers events which are * caught by the listeners attached to each one of the available GUI object * representations defined in the LoggingClient class. * Independent of that there are messages available at the logging system * generated by the other services running in the framework. These messages are * parsed by the ACSStructuredPushConsumer class using the SAX parser and are * then passed on using the LogTableDataModel's appendLog method for putting * the logs to the log table. * In particular, we are interested in the saving and loading of files to be * implemented by the LoggingClient. While saveFile and loadFromFile are defined * in LogTabledataModel, the LogImportTask file makes use of the * the LogTabledataModel's appendLog method as well. The use of the DocumentBuilderFactory * in the LogImportTask defines a way for transforming a DOM tree into XML. * <P> * An important issue is the format of the Log Entry Message produced by the Logging * Service. Certain characters ('<', '>', '&', ''', '"') need to be escaped * because they delineate markup data from character data and cause the following exception * in ACSLogParserDOM class: * org.xml.sax.SAXParseException: The content beginning with '<' * is not legal markup. * One solution is replacing the character with the appropriate html substitute <. * Another solution is keeping it in a CDATA section: <[!CDATA[the log entry message]]>. * <P> * The panel can be instantiated: * - by LogFrame * - as an EXEC plugin */ public class LoggingClient extends JRootPane implements ACSRemoteLogListener, ACSLogConnectionListener, ACSRemoteErrorListener, MessageWidgetListener { /** * The default log level */ public static final LogTypeHelper DEFAULT_LOGLEVEL = LogTypeHelper.INFO; /** * The default discard level */ public static final LogTypeHelper DEFAULT_DISCARDLEVEL = LogTypeHelper.DEBUG; /** * The name of the property to set for enabling the operator mode at startup. * * If the property is not found, ENGINEER audience is set in the engine * * @sse <code>initAudience()</code> */ private static final String AUDIENCE_PROPERTY = "jlog.mode.audience"; /** * The audience in use by the engine and shown in the status line */ private JLabel audienceLbl = new JLabel(); /** * The label showing if there are active filters in the engine */ private JLabel engineFiltersLbl = new JLabel(); /** * The label showing if there are active filters in the table */ private JLabel tableFiltersLbl = new JLabel(); /** * The label showing if the number of logs in memory is limited */ private JLabel maxNumOfLogsLbl = new JLabel(); private ArchiveConnectionManager archive; // Create an instance of the preferences with default values private UserPreferences userPreferences = new UserPreferences(0,100000,Integer.MAX_VALUE,Integer.MAX_VALUE); private JPanel ivjJPanel2 = null; private JPanel detailedInfoPanel = null; // The table showing the whole content of a log (in the detailed // panel at the right side of the main window) private DetailedLogTable detailedLogTable = new DetailedLogTable(); // The panel with the suspend btn, the filter string... // It is immediately under the table of logs private JPanel statusLinePnl = null; private JScrollPane statusAreaPanel = null; // The bottom scrolling panel with the status messages private JScrollPane detailedInfoScrollPane = null; /** * The horizontal split panel having the text area at the bottom * add the panel with the table and details (tableDetailsSplitPane) at the top. */ private JSplitPane statusAreaHrSplitP = null; /** * The vertical split pane having the table of logs at the left side, and the * details panel at the right side. */ private JSplitPane tableDetailsVrSplitP = null; private JScrollPane scrollLogTable = null; /** * The table of logs */ private LogEntryTable logEntryTable = null; /** * The status area at the bottom where messages are appended * by {@link #reportStatus(String)} */ private ExtendedTextArea messageTextArea = null; private JPanel ivjJFrameContentPane = null; /** * The error dialog */ private ErrorLogDialog errorDialog; /** * The progress bar for long time operations */ private JProgressBar progressBar = new JProgressBar(JProgressBar.HORIZONTAL,0,100); /** * The <code>ZoomManager</code> to perform zooming * <P> * The object is built with default levels; the path of the * folder of XML files is read from a java property. */ private ZoomManager zoom=new ZoomManager(); /** * The dialog to perform the zoom with a given time interval */ private ManualZoomDlg manualZoomDlg; /** * <code>true</code> if the engine is connected. */ private boolean isConnected=false; /** * <code>true</code> if the application is stopped * <P> * This property is set by the <code>start()</code> and <code>stop()</code>. * It is also set in the constructor for the stand alone version because in that * case the start is not executed. */ private volatile boolean isStopped=true; /** * The search dialog * The object is built the first time the user requests a search */ private SearchDialog searchDialog; /** * Statistic dialog. * The object is built the first time the user selects the menu item */ private StatsDlg statsDlg; /** * The dialog to query the database */ private QueryDlg databaseDlg=null; private EventHandler eventHandler = new EventHandler(); private LCEngine engine = null; private LogTableDataModel tableModel = null; /** * The icons to show the status of the connection * */ private static final int CONNECTED_ICON = 0; private static final int CONNECTING_ICON = 1; private static final int DISCONNECTED_ICON=2; private static final int SUSPENDED_ICON = 3; private static final int DELAY_ICON = 4; private ImageIcon[] connectionStatusIcons; /** * The label where icon is shown */ private JLabel connectionStatusLbl; /** * The label where the icon representing the status of the connection * with the DB is shown */ private JLabel connectionDBLbl; /** * The label where appears the icon to tell that there are * error in the jlog error log dialog */ private final JLabel jlogErrorLbl =new JLabel(new ImageIcon(this.getClass().getResource("/errorLogIcon.png"))); /** * The toolbar */ private LogToolBar toolBar; /** * The toolbar to navigate logs */ private LogNavigationBar navigationToolbar; /** * The menu bar */ private LogMenuBar menuBar = new LogMenuBar(); /** * The dialog to choose filters to apply to the engine */ private FilterChooserDialog engineFiltersDlg=null; /** * The error broser dialog */ private ErrorBrowserDlg errorBrowserDialog=null; /** * The dialog to manage table filters * There is only one instance of this dialog that can be visible or invisible. * It is disposed by calling the close() (usually done by * the LoggingClient before exiting. */ private FilterChooserDialog filterChooserDialog = null; /** * The frame containing this logging client. * It is not <code>null</code> only if the application is executed in stand alone mode */ private final LogFrame logFrame; /** * The following property is set if logs runs in debug mode */ private static final String DEBUG_MODE_PROPERTY="alma.acs.jlog.debugMode"; /** * <code>true</code> if jlog runs in debug mode */ private final boolean debugMode=Boolean.getBoolean(DEBUG_MODE_PROPERTY); /** * <code>containerServices</code> is always set while running as OMC plugin. * <P> * It is used to avoid creating a new ORB when one is already available. * * @see connect() */ protected ContainerServicesBase containerServices=null; /** * The glass pane showing messages to the user */ private MessageWidget errorWidget=new MessageWidget(); /** * The glass pane visible when jlog runs offline. */ private TransparentGlassPane glassPane; class EventHandler implements ActionListener, MenuListener { public void actionPerformed(java.awt.event.ActionEvent e) { if (e.getSource() == menuBar.getConnectMenuItem()) { connect(menuBar.getConnectMenuItem().getText().compareTo("Connect")==0); } else if (e.getSource() == menuBar.getLoadMenuItem()) { SwingUtilities.invokeLater(new Runnable() { public void run() { getLCModel1().loadFromFile(null); } }); } else if (e.getSource() == menuBar.getLoadURLMenuItem()) { SwingUtilities.invokeLater(new Runnable() { public void run() { getLCModel1().loadFromURL(); } }); } else if (e.getSource() == menuBar.getSaveFileMenuItem()) { SwingUtilities.invokeLater(new Runnable() { public void run() { getLCModel1().saveFile(); } }); } else if (e.getSource() == menuBar.getLoadDBMenuItem()) { if (archive.getDBStatus()==DBState.DATABASE_OK) { if (databaseDlg==null) { databaseDlg = new QueryDlg(archive,LoggingClient.this,LoggingClient.this,LoggingClient.this); } databaseDlg.setVisible(true); } } else if (e.getSource() == menuBar.getClearLogsMenuItem() || e.getSource()==toolBar.getClearLogsBtn()) { Thread t = new Thread("LoggingClient.clearAll") { public void run() { getLCModel1().clearAll(); } }; t.setDaemon(true); t.start(); } else if (e.getSource() == menuBar.getExitMenuItem()) { if (logFrame!=null) { // The application is executed in stand-alone mode // Signal the main window to close WindowEvent wEvt = new WindowEvent(logFrame,WindowEvent.WINDOW_CLOSING); logFrame.dispatchEvent(wEvt); } else { close(false); } }else if (e.getSource() == menuBar.getFieldsMenuItem()) { connFields(e); } else if (e.getSource() == menuBar.getFiltersMenuItem() || e.getSource()==toolBar.getFiltersBtn()) { showTableFiltersDialog(e); } else if (e.getSource()==toolBar.getPauseBtn()) { // Swap set the pause mode in the toolbar toolBar.clickPauseBtn(); // Pause/unpause the engine engine.setPaused(toolBar.isPaused()); } else if (e.getSource()==toolBar.getLogLevelCB()) { getLogEntryTable().setLogLevel((LogTypeHelper)toolBar.getLogLevelCB().getSelectedItem()); } else if (e.getSource()==toolBar.getDiscardLevelCB()){ getEngine().setDiscardLevel(LogTypeHelper.fromLogTypeDescription((String)toolBar.getDiscardLevelCB().getSelectedItem())); } else if (e.getSource()==navigationToolbar.getSearchBtn() || e.getSource()==menuBar.getSearchMenuItem()) { if (searchDialog==null) { searchDialog = new SearchDialog(LoggingClient.this); } searchDialog.setVisible(true); } else if (e.getSource()==menuBar.getSearchNextMenuItem()) { // The searchDialog is always not null otherwise the // menu item is disabled but... repetita juvant ;-) if (searchDialog!=null) { searchDialog.search(); } else { menuBar.getSearchNextMenuItem().setEnabled(false); } } else if (e.getSource()==menuBar.getViewToolbarMenuItem()) { // Hide/Show the toolbar toolBar.setVisible(menuBar.getViewToolbarMenuItem().getState()); } else if (e.getSource()==menuBar.getStatisticsMenuItem()) { // Show the statistics dialog class ShowStatisticDlg extends Thread { public void run() { getStatisticDialog().setVisible(true); } } ShowStatisticDlg showStat = new ShowStatisticDlg(); SwingUtilities.invokeLater(showStat); } else if (e.getSource()==menuBar.getViewErrorLogMenuItem()) { getJLogErroDialog().setVisible(true,LoggingClient.this); jlogErrorLbl.setVisible(false); } else if (e.getSource()==menuBar.getViewErrorBrowserMenuItem()) { getErrorDialog().setVisible(true); } else if (e.getSource()==menuBar.getViewStatusAreaMenuItem()) { getStatusAreaPanel().setVisible(menuBar.getViewStatusAreaMenuItem().getState()); if (menuBar.getViewStatusAreaMenuItem().getState()) { getStatusAreaHrPane().setDividerLocation(getHeight() - 150); } else { getStatusAreaHrPane().setDividerLocation(getHeight()); } } else if (e.getSource()==menuBar.getViewDetailedInfoMenuItem()) { getDeatailedInfoPanel().setVisible(menuBar.getViewDetailedInfoMenuItem().getState()); if (menuBar.getViewDetailedInfoMenuItem().getState()) { int w = getLogEntryTable().getWidth(); getTableDetailsVrPane().setDividerLocation(getTableDetailsVrPane().getWidth() - w/3); } else { getTableDetailsVrPane().setDividerLocation(getTableDetailsVrPane().getWidth()); } } else if (e.getSource()==menuBar.getAutoReconnectMenuItem()) { if (LoggingClient.this.engine!=null) { LoggingClient.this.engine.enableAutoReconnection(menuBar.getAutoReconnectMenuItem().getState()); } } else if (e.getSource()==menuBar.getShortDateViewMenuItem()) { logEntryTable.setShortDateFormat(menuBar.getShortDateViewMenuItem().isSelected()); } else if (e.getSource()==menuBar.getLogTypeDescriptionViewMenuItem()) { logEntryTable.setLogTypeDescriptionView(menuBar.getLogTypeDescriptionViewMenuItem().isSelected()); } else if (e.getSource()==toolBar.getPauseBtn()) { toolBar.clickPauseBtn(); } else if (e.getSource()==menuBar.getSuspendMenuItem()) { getEngine().setSupended(menuBar.getSuspendMenuItem().isSelected()); } else if (e.getSource()==menuBar.getPrefsMenuItem()) { ExpertPrefsDlg dlg = new ExpertPrefsDlg(LoggingClient.this,userPreferences); if (dlg.okPressed()) { UserPreferences newPrefs = dlg.getPreferences(); if (newPrefs.getMaxNumOfLogs()!=userPreferences.getMaxNumOfLogs()) { userPreferences.setMaxLogs(newPrefs.getMaxNumOfLogs()); getLCModel1().setMaxLog(userPreferences.getMaxNumOfLogs()); setNumberOfLogsLbl(); } if (newPrefs.getMinuteTimeFrame()!=userPreferences.getMinuteTimeFrame()) { userPreferences.setTimeFrame(userPreferences.getMinuteTimeFrame()); getLCModel1().setTimeFrame(userPreferences.getMillisecondsTimeFrame()); } if (newPrefs.getMaxInputRate()!=userPreferences.getMaxInputRate()) { userPreferences.setMaxInputRate(newPrefs.getMaxInputRate()); getEngine().setMaxInputRate(userPreferences.getMaxInputRate()); } if (newPrefs.getMaxOutputRate()!=userPreferences.getMaxOutputRate()) { userPreferences.setMaxOutputRate(newPrefs.getMaxOutputRate()); getEngine().setMaxOutputRate(userPreferences.getMaxOutputRate()); } if (newPrefs.getDynThreshold()!=userPreferences.getDynThreshold()) { userPreferences.setDynThreshold(newPrefs.getDynThreshold()); userPreferences.setDynDamping(newPrefs.getDynDamping()); userPreferences.setDynTime(newPrefs.getDynTime()); getEngine().enableDynamicDiscarding( userPreferences.getDynThreshold(), userPreferences.getDynDamping(), userPreferences.getDynTime()); } } } else if (e.getSource()==menuBar.getOperatorMode()) { getEngine().setAudience(AudienceInfo.OPERATOR.getAudience()); audienceLbl.setText(" "+AudienceInfo.OPERATOR.name+" "); } else if (e.getSource()==menuBar.getEngineeringMode()) { getEngine().setAudience(AudienceInfo.ENGINEER.getAudience()); audienceLbl.setText(" "+AudienceInfo.ENGINEER.name+" "); } else if (e.getSource()==menuBar.getSciLogMode()) { getEngine().setAudience(AudienceInfo.SCILOG.getAudience()); audienceLbl.setText(" "+AudienceInfo.SCILOG.name+" "); } else if (e.getSource()==menuBar.getEngineFiltersMenuItem()) { showEngineFiltersDialog(); } else if (e.getSource()==menuBar.getZoomPrefsMI()) { ZoomPrefsDlg dlg = new ZoomPrefsDlg(LoggingClient.this,zoom); boolean zoomAvailable=zoom.isAvailable(); toolBar.setZoomable(zoomAvailable && logEntryTable.getSelectedRowCount()>1); menuBar.getManualZoomMI().setEnabled(zoomAvailable); } else if (e.getSource()==menuBar.getManualZoomMI()) { class ShowManualZoom extends Thread { public void run() { if (manualZoomDlg==null) { manualZoomDlg=new ManualZoomDlg(LoggingClient.this,zoom); } manualZoomDlg.setVisible(true); } } SwingUtilities.invokeLater(new ShowManualZoom()); } else if (e.getSource()==toolBar.getZoomBtn()) { Thread t = new Thread(new Runnable() { public void run() { logEntryTable.zoom(); } }); t.setDaemon(true); t.setName("LoggingClient.actionPerformed.Zoom"); t.start(); } else { System.err.println("Unrecognized ActionEvent "+e); } }; public void menuCanceled(MenuEvent menuE) {} public void menuDeselected(MenuEvent menuE) {} public void menuSelected(MenuEvent menuE) { // Some menus are disabled when loading/saving boolean enableMenu = !getLCModel1().IOInProgress(); menuBar.getClearLogsMenuItem().setEnabled(enableMenu); if (getEngine().isConnected()) { menuBar.getConnectMenuItem().setText("Disconnect"); } else { menuBar.getConnectMenuItem().setText("Connect"); } menuBar.getConnectMenuItem().setEnabled(enableMenu); menuBar.getLoadMenuItem().setEnabled(enableMenu); menuBar.getLoadURLMenuItem().setEnabled(enableMenu); menuBar.getSaveFileMenuItem().setEnabled(enableMenu); // Ensure the status of the item shown in the main panel // is consistent with the menu item in View menuBar.getViewStatusAreaMenuItem().setSelected(getStatusAreaPanel().isVisible()); menuBar.getViewDetailedInfoMenuItem().setSelected(getDeatailedInfoPanel().isVisible()); menuBar.getViewToolbarMenuItem().setSelected(toolBar.isVisible()); // This button is always disabled since when the logs are not stored in the DB // see ICT-1649 // If you want to enable depending on the avalability of the DB // the replace false below with "archive.getDBStatus()==DBState.DATABASE_OK" menuBar.getLoadDBMenuItem().setEnabled(false); } } /** * Constructor * <P> * The empty constructor is called by the OMC GUI. * */ public LoggingClient() { super(); logFrame=null; initialize(DEFAULT_LOGLEVEL,DEFAULT_DISCARDLEVEL,false); initAudience(null); } /** * The constructor * <P> * This constructor is called when this object runs in stand-alone mode * i.e outside of the OMC GUI. * * @param frame The shows this object * @param logLevel The initial log level * @param discardLevel The initial discard level * @param unlimited If <code>true</code> the number of logs in memory is unlimited, * otherwise the default is used */ public LoggingClient( LogFrame frame, LogTypeHelper logLevel, LogTypeHelper discardLevel, boolean unlimited, AudienceInfo aInfo) { super(); isStopped=false; logFrame=frame; initialize(logLevel, discardLevel, unlimited); initAudience(aInfo); } /** * Method used by the plugin interface in EXEC: * it connects the application to the NC * * @see alma.exec.extension.subsystemplugin.SubsystemPlugin * * @throws Exception */ public void start() throws Exception { if (containerServices==null) { throw new IllegalArgumentException("Starting the plugin without setting the ContainerServices"); } isStopped=false; connect(); } /** * Method used by the plugin interface in EXEC. * Stop the application disconnecting from the NC * @see alma.exec.extension.subsystemplugin.SubsystemPlugin * * @throws Exception */ public void stop() throws Exception { isStopped=true; close(false); } /** * Method used by the plugin interface in EXEC. * Pause the application (scroll lock enabled) * @see alma.exec.extension.subsystemplugin.IPauseResume * * @throws Exception */ public void pause() throws Exception { toolBar.pause(); engine.setPaused(true); } /** * Method used by the plugin interface in EXEC. * Unpause the application (scroll lock disabled) * @see alma.exec.extension.subsystemplugin.IPauseResume * * @throws Exception */ public void resume() throws Exception { toolBar.unpause(); engine.setPaused(false); } /** * Connect or disconnect the engine to the NC * * @param connect If true the engine is connected * otherwise it is disconnected */ public void connect(boolean connectEngine) { if (connectEngine) { // Check and eventually un-suspend the engine menuBar.getSuspendMenuItem().setSelected(false); getEngine().setSupended(menuBar.getSuspendMenuItem().isSelected()); // Connect the the channel connect(); } else { menuBar.getAutoReconnectMenuItem().setState(false); LoggingClient.this.engine.enableAutoReconnection(false); disconnect(); } } /** * Connects to the remote system * as soon as the item "New" is clicked. */ public void connect() { if (containerServices!=null) { ORB orb=null; AdvancedContainerServices advContSvc = containerServices.getAdvancedContainerServices(); if (advContSvc!=null) { orb = advContSvc.getORB(); getEngine().setConnectionParams(orb, null); } } try { getEngine().connect("ACS"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } } private void disconnect() { getEngine().disconnect(); } /** * Triggers the Field Choser's dialog visual appearance * as soon as the item "Fields" is clicked. * @param arg1 java.awt.event.ActionEvent */ private void connFields(java.awt.event.ActionEvent arg1) { try { getLogEntryTable().showFieldChooser(); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } } /** Triggers the Filters dialog visual appearance * as soon as the item "Filters" is clicked. * @param arg1 java.awt.event.ActionEvent */ private void showTableFiltersDialog(java.awt.event.ActionEvent arg1) { class TableFilterable implements Filterable { /* (non-Javadoc) * @see com.cosylab.logging.engine.Filterable#getFilters() */ @Override public FiltersVector getFilters() { return logEntryTable.getFilters(); } /* (non-Javadoc) * @see com.cosylab.logging.engine.Filterable#setFilters(com.cosylab.logging.engine.FiltersVector, boolean) */ @Override public void setFilters(FiltersVector newFilters, boolean append) { logEntryTable.setFilters(newFilters, append); setTableFilterLbl(); } } if (filterChooserDialog==null) { filterChooserDialog=new FilterChooserDialog("Filter chooser",this,new TableFilterable()); } filterChooserDialog.setFilters(logEntryTable.getFilters()); SwingUtilities.invokeLater(new Runnable() { public void run() { enableFiltersWidgets(false); filterChooserDialog.setVisible(true); } }); } /** * Update the label of the filtering of the table */ public void setTableFilterLbl() { SwingUtilities.invokeLater(new Runnable() { public void run() { if (logEntryTable.getFilters().hasActiveFilters()) { tableFiltersLbl.setForeground(Color.RED); tableFiltersLbl.setText("Table filtered"); tableFiltersLbl.setToolTipText(logEntryTable.getFiltersString()); } else { tableFiltersLbl.setForeground(Color.BLACK); tableFiltersLbl.setText("Table not filtered"); tableFiltersLbl.setToolTipText(null); } } }); } /** * Update the label with the number of logs in memory */ private void setNumberOfLogsLbl() { SwingUtilities.invokeLater(new Runnable() { public void run() { int nLogs=userPreferences.getMaxNumOfLogs(); if (nLogs>0) { String str=Integer.toString(nLogs); if (str.length()>3) { str = str.substring(0, str.length()-3)+"K"; } maxNumOfLogsLbl.setForeground(Color.RED); maxNumOfLogsLbl.setText(str); maxNumOfLogsLbl.setToolTipText("The number of logs to keep in memory is limited to "+str); } else { maxNumOfLogsLbl.setForeground(Color.BLACK); maxNumOfLogsLbl.setText("Unlimited"); maxNumOfLogsLbl.setToolTipText("The number of logs to keep in memory is unlimited"); } } }); } /** * Update the label of the filtering of the table */ private void setEngineFilterLbl() { SwingUtilities.invokeLater(new Runnable() { public void run() { if (engine==null || engine.getFilters()==null || !engine.getFilters().hasActiveFilters()) { engineFiltersLbl.setForeground(Color.BLACK); engineFiltersLbl.setText("Engine not filtered"); engineFiltersLbl.setToolTipText(null); } else { engineFiltersLbl.setForeground(Color.RED); engineFiltersLbl.setText("Engine filtered"); engineFiltersLbl.setToolTipText(engine.getFiltersString()); } } }); } /** * Returns the JFrameContentPane property value. * @return javax.swing.JPanel */ private JPanel getJFrameContentPane() { if (ivjJFrameContentPane == null) { try { ivjJFrameContentPane = new JPanel(); ivjJFrameContentPane.setName("JFrameContentPane"); ivjJFrameContentPane.setLayout(new BorderLayout()); ivjJFrameContentPane.add(getStatusAreaHrPane(), "Center"); } catch (Throwable ivjExc) { handleException(ivjExc); } } return ivjJFrameContentPane; } /** * CustomColumnListener implements componentResized() of a ComponentListener. * It has been added to JScrollPane scrollLogTable to increase the width of * the Log Message column as soon as the space is available. */ private class CustomColumnListener implements ComponentListener { public void componentShown(ComponentEvent evt) { } public void componentHidden(ComponentEvent evt) { } public void componentMoved(ComponentEvent evt) { } // This method is called after the component's size changes public void componentResized(ComponentEvent evt) { // gets the component JTable LogEntryTable that has been changed Component c = (Component) evt.getSource(); // gets the width of JTable LogEntryTable // in case a vertical ScrollBar appears the width remains the same int tableWidthTobe = c.getSize().width; // sets a preferred size to JScrollPane getLogEntryTable().setPreferredScrollableViewportSize(new Dimension(tableWidthTobe, c.getSize().height)); // gets the number of columns in JTable LogEntryTable int numCols = getLogEntryTable().getColumnModel().getColumnCount(); // computes the width of the table taking into consideration all visible columns int columnWidth = getLogEntryTable().getColumnWidth(numCols); // adds width to the Log Message column getLogEntryTable().setAdditionalWidth(numCols, tableWidthTobe - columnWidth); } } /** * Returns the scroll panel with the table of logs * @return the scroll panel with the table of logs */ public JScrollPane getLogTableScroolP() { if (scrollLogTable == null) { try { scrollLogTable = new JScrollPane(getLogEntryTable(),JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollLogTable.setName("scrollLogTable"); scrollLogTable.setBackground(new Color(204, 204, 204)); scrollLogTable.setFont(new Font("Arial", 1, 12)); scrollLogTable.setMinimumSize(new Dimension(100, 50)); scrollLogTable.addComponentListener(new CustomColumnListener()); scrollLogTable.getViewport().setScrollMode(JViewport.BLIT_SCROLL_MODE); } catch (Throwable ivjExc) { handleException(ivjExc); } } return scrollLogTable; } /** * Returns the table of logs * @return the table of logs */ public LogEntryTable getLogEntryTable() { if (logEntryTable == null) { try { logEntryTable = new LogEntryTable( this, menuBar.getShortDateViewMenuItem().isSelected(), menuBar.getLogTypeDescriptionViewMenuItem().isSelected()); logEntryTable.setName("logEntryTable"); logEntryTable.setBounds(0, 0, 200, 200); tableModel=logEntryTable.getLCModel(); } catch (Throwable ivjExc) { handleException(ivjExc); } } return logEntryTable; } /** * Called whenever the part throws an exception. * @param exception java.lang.Throwable */ private void handleException(java.lang.Throwable exception) { showErrorMessage("Uncaught exception", exception); } /** * Initializes connections and adds listeners to all the menus and menu items. * @exception java.lang.Exception The exception description. */ private void initConnections() throws java.lang.Exception { menuBar.setEventHandler(eventHandler, eventHandler); toolBar.setEventHandler(eventHandler); navigationToolbar.setEventHandler(eventHandler); } /** * Initializes the object. * * @param logLevel The initial log level to set in the toolbar and in the table * @param discardLevel The initial discard level to set in the toolbar and in the engine * @param unlimited If <code>true</code> the number of logs in memory is unlimited, * otherwise the default is used */ private void initialize(LogTypeHelper logLevel, LogTypeHelper discardLevel, boolean unlimited) { try { setName("LoggingClientPanel"); messageTextArea = new ExtendedTextArea(); // Set the glass pane showing errors and messages to be acknowledged glassPane = new TransparentGlassPane(getContentPane()); setGlassPane(glassPane); // We want to be notified when the user presses the Ok button // of the MessageWidget errorWidget.addAckListener(this); // Set the tooltip manager ToolTipManager toolTipManager = ToolTipManager.sharedInstance(); toolTipManager.setDismissDelay(60000); Dimension d = new Dimension(750, 550); setPreferredSize(d); getContentPane().setLayout(new BorderLayout()); setJMenuBar(menuBar); // Add the GUI in the center position getContentPane().add(getJFrameContentPane(),BorderLayout.CENTER); // The panel having the toolbars on top and the panel showing errors at the bottom JPanel northPanel = new JPanel(new BorderLayout()); // Add the toolbars to the toolbarsPanel JPanel toolbarsPanel = new JPanel(); BoxLayout toolbarLayout = new BoxLayout(toolbarsPanel,BoxLayout.Y_AXIS); toolbarsPanel.setLayout(toolbarLayout); toolBar = new LogToolBar(logLevel,discardLevel); boolean zoomAvailable=zoom.isAvailable(); toolBar.setZoomable(zoomAvailable); menuBar.getManualZoomMI().setEnabled(zoomAvailable); toolbarsPanel.add(toolBar); navigationToolbar = new LogNavigationBar(getLogEntryTable()); toolbarsPanel.add(navigationToolbar); northPanel.add(toolbarsPanel,BorderLayout.NORTH); northPanel.add(errorWidget,BorderLayout.SOUTH); getContentPane().add(northPanel,BorderLayout.NORTH); initConnections(); validate(); getLogEntryTable().setLogLevel((LogTypeHelper)toolBar.getLogLevelCB().getSelectedItem()); if (unlimited) { userPreferences.setMaxLogs(0); } getLCModel1().setTimeFrame(userPreferences.getMillisecondsTimeFrame()); getLCModel1().setMaxLog(userPreferences.getMaxNumOfLogs()); archive = new ArchiveConnectionManager(this); setTableFilterLbl(); setEngineFilterLbl(); setNumberOfLogsLbl(); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } getTableDetailsVrPane().setDividerLocation(getTableDetailsVrPane().getLastDividerLocation()); getStatusAreaHrPane().setDividerLocation(350); //getHeight() - 150); } /** * Show a detailed view of the selected log in the right panel */ public void showDetailedLogInfo() { try { LogEntryTable jt = getLogEntryTable(); int selectedRow = jt.getSelectedRow(); // Check whether a row has been selected // no row selected if (selectedRow == -1) { detailedLogTable.setupContent(null); } else { // a row is selected ILogEntry log = jt.getLCModel().getVisibleLogEntry(selectedRow); detailedLogTable.setupContent(log); } } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } } /** * Set the content of the detailed info table from the given log * * @param log The log entry which fields have to be shown in the table * It can be <code>null</code> */ public void setLogDetailContent(ILogEntry log) { // Try to build a DetailedLogTable class DetailedLogFiller implements Runnable { public ILogEntry logToWrite; public void run() { detailedLogTable.setupContent(logToWrite); } } DetailedLogFiller filler = new DetailedLogFiller(); filler.logToWrite=log; SwingUtilities.invokeLater(filler); } /** * Disconnects the LCEngine. * @param arg1 java.awt.event.WindowEvent */ public void connLCEngDisconnect(WindowEvent arg1) { try { getEngine().disconnect(); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } } /** * Returns the JPanel2 property value. * @return javax.swing.JPanel */ private JPanel getJPanel2() { if (ivjJPanel2 == null) { try { ivjJPanel2 = new JPanel(); ivjJPanel2.setName("JPanel2"); ivjJPanel2.setLayout(new BorderLayout()); ivjJPanel2.add(getStatusLinePnl(), "South"); ivjJPanel2.add(getTableDetailsVrPane(), "Center"); } catch (Throwable ivjExc) { handleException(ivjExc); } } return ivjJPanel2; } /** * Returns the JPanel3 property value. * @return javax.swing.JPanel */ private JPanel getDeatailedInfoPanel() { if (detailedInfoPanel == null) { try { BorderLayout layout = new BorderLayout(); layout.setVgap(10); detailedInfoPanel = new JPanel(layout); detailedInfoPanel.setName("detailedInfoPanel"); JLabel lbl =new JLabel("Detailed info"); detailedInfoPanel.add(lbl,BorderLayout.NORTH); detailedInfoPanel.add(getLogDetailScrollPane(), BorderLayout.CENTER); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } } return detailedInfoPanel; } /** * Returns the panel for the status line * * @return the panel for the status line */ private JPanel getStatusLinePnl() { if (statusLinePnl == null) { try { // Load the icons for the status of the connection connectionStatusIcons = new ImageIcon[5]; connectionStatusIcons[CONNECTED_ICON]=new ImageIcon(this.getClass().getResource("/console-connected.png")); connectionStatusIcons[CONNECTING_ICON]=new ImageIcon(this.getClass().getResource("/console-connecting.png")); connectionStatusIcons[DISCONNECTED_ICON]=new ImageIcon(this.getClass().getResource("/console-disconnected.png")); connectionStatusIcons[SUSPENDED_ICON]=new ImageIcon(this.getClass().getResource("/console-suspended.png")); connectionStatusIcons[DELAY_ICON]=new ImageIcon(this.getClass().getResource("/console-delay.png")); connectionStatusLbl = new JLabel(connectionStatusIcons[CONNECTING_ICON]); // Create a label to show the status of the connection with the DB connectionDBLbl = new JLabel(); statusLinePnl = new javax.swing.JPanel(); statusLinePnl.setName("Status_line"); statusLinePnl.setLayout(new java.awt.GridBagLayout()); GridBagConstraints constraintsProgressBar = new GridBagConstraints(); constraintsProgressBar.gridx=0; constraintsProgressBar.gridy=0; constraintsProgressBar.fill = GridBagConstraints.BOTH; constraintsProgressBar.anchor = GridBagConstraints.WEST; constraintsProgressBar.weightx = 1.0; constraintsProgressBar.insets = new Insets(1, 2, 1, 1); statusLinePnl.add(progressBar,constraintsProgressBar); GridBagConstraints constraintsNumFlt = new GridBagConstraints(); constraintsNumFlt.gridx=1; constraintsNumFlt.gridy=0; constraintsNumFlt.insets = new Insets(1,1,1,1); maxNumOfLogsLbl.setVisible(true); maxNumOfLogsLbl.setBorder(BorderFactory.createLoweredBevelBorder()); Font fntNumFlt = maxNumOfLogsLbl.getFont(); Font newFontNumFlt = fntNumFlt.deriveFont(fntNumFlt.getSize()-2); maxNumOfLogsLbl.setFont(newFontNumFlt); statusLinePnl.add(maxNumOfLogsLbl,constraintsNumFlt); GridBagConstraints constraintsEngineFlt = new GridBagConstraints(); constraintsEngineFlt.gridx=2; constraintsEngineFlt.gridy=0; constraintsEngineFlt.insets = new Insets(1,1,1,1); engineFiltersLbl.setVisible(true); engineFiltersLbl.setBorder(BorderFactory.createLoweredBevelBorder()); Font fntEngineFlt = engineFiltersLbl.getFont(); Font newFontEngineFlt = fntEngineFlt.deriveFont(fntEngineFlt.getSize()-2); engineFiltersLbl.setFont(newFontEngineFlt); statusLinePnl.add(engineFiltersLbl,constraintsEngineFlt); GridBagConstraints constraintsTableFlt= new GridBagConstraints(); constraintsTableFlt.gridx=3; constraintsTableFlt.gridy=0; constraintsTableFlt.insets = new Insets(1,1,1,1); tableFiltersLbl.setVisible(true); tableFiltersLbl.setBorder(BorderFactory.createLoweredBevelBorder()); Font fntTableFlt = tableFiltersLbl.getFont(); Font newFontTableFlt = fntTableFlt.deriveFont(fntTableFlt.getSize()-2); tableFiltersLbl.setFont(newFontTableFlt); statusLinePnl.add(tableFiltersLbl,constraintsTableFlt); GridBagConstraints constraintsAudience = new GridBagConstraints(); constraintsAudience.gridx=4; constraintsAudience.gridy=0; constraintsAudience.insets = new Insets(1,1,1,1); audienceLbl.setVisible(true); audienceLbl.setBorder(BorderFactory.createLoweredBevelBorder()); Font fnt = audienceLbl.getFont(); Font newFont = fnt.deriveFont(fnt.getSize()-2); audienceLbl.setFont(newFont); statusLinePnl.add(audienceLbl,constraintsAudience); GridBagConstraints constraintsConnectionDBStatus = new GridBagConstraints(); constraintsConnectionDBStatus.gridx = 5; constraintsConnectionDBStatus.gridy = 0; constraintsConnectionDBStatus.insets = new Insets(1, 2, 1, 2); statusLinePnl.add(connectionDBLbl,constraintsConnectionDBStatus); GridBagConstraints constraintsJlogErrors = new GridBagConstraints(); constraintsConnectionDBStatus.gridx = 6; constraintsConnectionDBStatus.gridy = 0; constraintsConnectionDBStatus.insets = new Insets(1, 2, 1, 2); statusLinePnl.add(jlogErrorLbl,constraintsJlogErrors); jlogErrorLbl.setVisible(false); jlogErrorLbl.setToolTipText("Error reading logs"); jlogErrorLbl.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { jlogErrorLbl.setVisible(false); errorDialog.setVisible(true,LoggingClient.this); super.mouseClicked(e); } }); GridBagConstraints constraintsConnectionStatus = new GridBagConstraints(); constraintsConnectionStatus.gridx = 7; constraintsConnectionStatus.gridy = 0; constraintsConnectionStatus.insets = new Insets(1, 2, 1, 2); statusLinePnl.add(connectionStatusLbl,constraintsConnectionStatus); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } } return statusLinePnl; } /** * Returns the JScrollPane1 property value. * @return javax.swing.JScrollPane */ private javax.swing.JScrollPane getStatusAreaPanel() { if (statusAreaPanel == null) { try { statusAreaPanel = new javax.swing.JScrollPane(); statusAreaPanel.setName("JScrollPane1"); statusAreaPanel.setVerticalScrollBarPolicy(javax.swing.JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); statusAreaPanel.setPreferredSize(new java.awt.Dimension(50, 50)); statusAreaPanel.setMinimumSize(new java.awt.Dimension(50, 50)); statusAreaPanel.setViewportView(messageTextArea); statusAreaPanel.setVisible(false); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } } return statusAreaPanel; } /** * Returns the scroll pane with the details of the logs * * @return JScrollPane */ public JScrollPane getLogDetailScrollPane() { if (detailedInfoScrollPane == null) { try { detailedInfoScrollPane = new JScrollPane(detailedLogTable); detailedInfoScrollPane.setName("detailedInfoScrollPane"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } } return detailedInfoScrollPane; } /** * Returns the JSplitPane1 property value. * @return javax.swing.JSplitPane */ private JSplitPane getStatusAreaHrPane() { if (statusAreaHrSplitP == null) { try { statusAreaHrSplitP = new JSplitPane(JSplitPane.VERTICAL_SPLIT); statusAreaHrSplitP.setName("JSplitPane1"); statusAreaHrSplitP.setLastDividerLocation(350); statusAreaHrSplitP.setDividerLocation(350); statusAreaHrSplitP.add(getStatusAreaPanel(), "bottom"); statusAreaHrSplitP.add(getJPanel2(), "top"); } catch (Throwable ivjExc) { handleException(ivjExc); } } return statusAreaHrSplitP; } /** * @return the split pane with the table of logs and the table with the details of a log */ private JSplitPane getTableDetailsVrPane() { if (tableDetailsVrSplitP == null) { try { tableDetailsVrSplitP = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); tableDetailsVrSplitP.setName("TableDetailsSplitPane"); tableDetailsVrSplitP.setLastDividerLocation(570); tableDetailsVrSplitP.setAlignmentX(Component.LEFT_ALIGNMENT); tableDetailsVrSplitP.setContinuousLayout(true); //ivjJSplitPane2.setDividerLocation(501); tableDetailsVrSplitP.add(getLogTableScroolP(),"left"); tableDetailsVrSplitP.add(getDeatailedInfoPanel(), "right"); } catch (Throwable ivjExc) { handleException(ivjExc); } } return tableDetailsVrSplitP; } /** * Returns the LCEngine property value. * @return com.cosylab.logging.LCEngine */ public LCEngine getEngine() { if (engine == null) { try { engine = new LCEngine(); engine.addLogConnectionListener(this); engine.addLogListener(this); engine.addLogErrorListener(this); engine.setDiscardLevel(LogTypeHelper.fromLogTypeDescription((String)toolBar.getDiscardLevelCB().getSelectedItem())); if (logFrame!=null) { engine.addLogConnectionListener(logFrame); } } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } } return engine; } /** * Returns the LCModel1 property value. * @return com.cosylab.logging.LogTableDataModel */ public LogTableDataModel getLCModel1() { return tableModel; } /** * Sets the height and width generated by user's actions. */ public void loggingClient_ComponentResized(ComponentEvent e) { if (e.getComponent() == this) { int w = getLogEntryTable().getWidth(); int h = getLogEntryTable().getHeight(); System.out.println(w + ", " + h); System.out.println(getTableDetailsVrPane().getWidth()); System.out.println(getStatusAreaHrPane().getHeight()); getTableDetailsVrPane().setDividerLocation(getTableDetailsVrPane().getWidth() - w); getStatusAreaHrPane().setDividerLocation(getStatusAreaHrPane().getHeight() - h); } } /** * Sets the LCModel1 to a new value. * @param newValue com.cosylab.logging.LogTableDataModel */ private void setLCModel1(LogTableDataModel newValue) { if (tableModel != newValue) { try { tableModel = newValue; } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; } /** * Enable or disable the Search next menu item * (tipically this action is preformed by the SearchDialog when a valid search * is performed) * * @param enable true enable the searchNextMenuItem */ public void enableSearchNext(boolean enable) { menuBar.getSearchNextMenuItem().setEnabled(enable); } /** * Show the progres bar as determinate with the given min and max * * @param textThe text to show in the toolbar * If it is null or empty then no text will be displayed * @param min The starting position * @param max The final position */ public void animateProgressBar(final String text, final int min, final int max) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (min>=max) { throw new IllegalArgumentException("Invalid range: ["+min+","+max+"]"); } Cursor hourglassCursor = new Cursor(Cursor.WAIT_CURSOR); setCursor(hourglassCursor); if (text!=null && text.length()>0) { progressBar.setString(text); progressBar.setStringPainted(true); progressBar.setToolTipText(text); } else { progressBar.setStringPainted(false); progressBar.setToolTipText("Wait please"); } progressBar.setMinimum(min); progressBar.setMaximum(max); progressBar.setIndeterminate(false); progressBar.setVisible(true); } }); } /** * Move the progressbar when in determinate mode * @param newPos */ public void moveProgressBar(final int newPos) { SwingUtilities.invokeLater(new Runnable() { public void run() { progressBar.setValue(newPos); } }); } /** * Show the progress bar as indeterminate * *@param text The text to show in the toolbar * If it is null or empty then no text will be displayed */ public void animateProgressBar(final String text) { SwingUtilities.invokeLater(new Runnable() { public void run() { Cursor hourglassCursor = new Cursor(Cursor.WAIT_CURSOR); setCursor(hourglassCursor); if (text!=null && text.length()>0) { progressBar.setString(text); progressBar.setStringPainted(true); progressBar.setToolTipText(text); } else { progressBar.setStringPainted(false); progressBar.setToolTipText("Wait please"); } progressBar.setIndeterminate(true); } }); } /** * Hide the progress bar (i.e. a long operation * has terminated) */ public void freezeProgressBar() { SwingUtilities.invokeLater(new Runnable() { public void run() { progressBar.setIndeterminate(false); progressBar.setMinimum(0); progressBar.setMaximum(100); progressBar.setValue(0); progressBar.setStringPainted(false); progressBar.setToolTipText(null); Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR); setCursor(normalCursor); } }); } /** * @return true if the application is connected to the notification channel * */ public boolean isConnected() { return isConnected; } /** * * @return The discard log level * @see LoggingClient.discardLevelCB */ public int getDiscardLevel() { return toolBar.getDiscardLevelCB().getSelectedIndex(); } /** * @see com.cosylab.logging.engine.ACS.ACSRemoteLogListener */ public void logEntryReceived(ILogEntry logEntry) { getLogEntryTable().getLCModel().appendLog(logEntry); } /** * Append the report status message to the status area * * @see com.cosylab.logging.engine.ACS.ACSRemoteLogListener */ public void reportStatus(String status) { messageTextArea.append(status); } /** * Notify that the connection with ACS NC has been established * @see com.cosylab.logging.engine.ACS.ACSLogConnectionListener */ public void acsLogConnEstablished() { isConnected=true; connectionStatusLbl.setIcon(connectionStatusIcons[CONNECTED_ICON]); connectionStatusLbl.setToolTipText("Connected"); glassPane.setVisible(false); if (errorWidget.getAckButton().isVisible()) { errorWidget.getAckButton().doClick(); } } /** * * @see com.cosylab.logging.engine.ACS.ACSLogConnectionListener */ public void acsLogConnDisconnected() { isConnected=false; connectionStatusLbl.setIcon(connectionStatusIcons[DISCONNECTED_ICON]); connectionStatusLbl.setToolTipText("Disconnected"); glassPane.setVisible(true); } /** * Notify that the connection with ACS NC has been lost *@see com.cosylab.logging.engine.ACS.ACSLogConnectionListener */ public void acsLogConnLost() { isConnected=false; // Does not show the dialog if the application is stopped if (isStopped) { return; } glassPane.setVisible(true); showErrorMessage("Connection lost",null); } /** * Notify that an attempt to connect to ACS NC is in progress * @see com.cosylab.logging.engine.ACS.ACSLogConnectionListener */ public void acsLogConnConnecting() { connectionStatusLbl.setIcon(connectionStatusIcons[CONNECTING_ICON]); connectionStatusLbl.setToolTipText("Connecting"); } /** * Notify that the service is suspended * @see com.cosylab.logging.engine.ACS.ACSLogConnectionListener */ public void acsLogConnSuspended() { connectionStatusLbl.setIcon(connectionStatusIcons[SUSPENDED_ICON]); connectionStatusLbl.setToolTipText("Suspended"); } /** * Notify that for some internal reason the service is not able * to follow the flow of the incoming logs * @see com.cosylab.logging.engine.ACS.ACSRemoteLogListener */ public void acsLogsDelay() { connectionStatusLbl.setIcon(connectionStatusIcons[DELAY_ICON]); connectionStatusLbl.setToolTipText("Delay"); } /** * Update the GUI with the status of the DB connection * * @param icon The icon * @param msg A message to show as tooltip */ public void showDBStatus(ImageIcon icon,String msg) { connectionDBLbl.setIcon(icon); connectionDBLbl.setToolTipText(msg); } /** * @return A reference to the preferences */ public UserPreferences getPrefs() { return userPreferences; } /** * Return true if the application is paused * * @return */ public boolean isPaused() { return toolBar.isPaused(); } /** * Hide the Exit menu item * * @param hide If true the menu is set to invisible */ public void hideExitMenu(boolean hide) { menuBar.hideExitMenu(hide); } /** * Close all the threads and release all the resources * @param sync If it is true wait the termination of the threads before returning */ public void close(boolean sync) { setVisible(false); if (tableModel!=null) { tableModel.close(sync); } if (logEntryTable!=null) { logEntryTable.close(); } if (engine!=null) { engine.close(sync); } if (errorDialog!=null) { errorDialog.setVisible(false); errorDialog.dispose(); errorDialog=null; } if (statsDlg!=null) { statsDlg.setVisible(false); statsDlg.dispose(); statsDlg=null; } if (searchDialog!=null) { searchDialog.setVisible(false); searchDialog.dispose(); searchDialog=null; } if (engineFiltersDlg!=null) { engineFiltersDlg.setVisible(false); engineFiltersDlg.dispose(); engineFiltersDlg=null; } if (filterChooserDialog!=null) { filterChooserDialog.setVisible(false); filterChooserDialog.dispose(); filterChooserDialog=null; } if (errorBrowserDialog!=null) { errorBrowserDialog.close(); errorBrowserDialog=null; } if (databaseDlg!=null) { databaseDlg.close(); databaseDlg=null; } if (manualZoomDlg!=null) { manualZoomDlg.close(); manualZoomDlg=null; } } /** * Enable/disable the filter menu item and the filter button * in the tool bar. * <p> * Calling this method overwrites the setting of the tool bar's "filtersBtn" * via {@link LogToolBar#setEnabled(boolean)}. * This feature is needed to disable this button when jlog runs inside the OMC, * because there we get calls to LogToolBar#setEnabled(true) * for every table update, menu opening etc. * * @param enable true enables the widgets */ public void enableFiltersWidgets(boolean enable) { toolBar.enableFiltersButtonOverwrite(enable); toolBar.setEnabled(enable); menuBar.getFiltersMenuItem().setEnabled(enable); menuBar.getEngineFiltersMenuItem().setEnabled(enable); } /** * @see ACSRemoteErrorListener */ public void errorReceived(String xml) { StringBuilder str = new StringBuilder("Error parsing the following log: \n"); str.append(xml); str. append("\n The log has been lost.\n\n"); getJLogErroDialog().appendText(str.toString()); if (!getJLogErroDialog().isVisible()) { jlogErrorLbl.setVisible(true); } } /** * Return a dialog showing the statistics * * @return The dialog showing the statistic */ public StatsDlg getStatisticDialog() { if (statsDlg==null) { statsDlg=new StatsDlg(this); } return statsDlg; } /** * Init the audience. * <P> * If an audience has been specified in the command line then * it will be used otherwise it tries to check if a java property * has been set. * <BR> * The audience dafaults to ENGINEER. * * @param audienceInfo The audience: it can be <code>null</code>. */ protected void initAudience(AudienceInfo audienceInfo) { AudienceInfo aInfo=null; if (audienceInfo!=null) { // Audience set in the command line aInfo=audienceInfo; } else { String audienceProp=System.getProperty(AUDIENCE_PROPERTY); if (audienceProp==null || audienceProp.isEmpty()) { menuBar.getEngineeringMode().doClick(); return; } aInfo=AudienceInfo.fromShortName(audienceProp); if (aInfo==null) { // Invalid property name System.err.println(audienceProp+" is not a valid audience: using default audience"); System.err.println("Available audiences are: "); for (String aShortName: AudienceInfo.getShortNames()) { System.err.println("\t"+aShortName); } menuBar.getEngineeringMode().doClick(); return; } } switch (aInfo) { case ENGINEER: { menuBar.getEngineeringMode().doClick(); return; } case OPERATOR: { menuBar.getOperatorMode().doClick(); return; } case SCILOG: { menuBar.getSciLogMode().doClick(); return; } default: { // Unknown audience menuBar.getEngineeringMode().doClick(); return; } } } /** * Shows the dialog to set filters in the engine */ private void showEngineFiltersDialog() { class EngineFilterable implements Filterable { /* (non-Javadoc) * @see com.cosylab.logging.engine.Filterable#getFilters() */ @Override public FiltersVector getFilters() { return engine.getFilters(); } /* (non-Javadoc) * @see com.cosylab.logging.engine.Filterable#setFilters(com.cosylab.logging.engine.FiltersVector, boolean) */ @Override public void setFilters(FiltersVector newFilters, boolean append) { engine.setFilters(newFilters, append); setEngineFilterLbl(); } } if (engineFiltersDlg==null) { engineFiltersDlg = new FilterChooserDialog("Engine filters",this,new EngineFilterable()); } FiltersVector engineFilters = engine.getFilters(); if (engineFilters==null) { engineFilters = new FiltersVector(); } engineFiltersDlg.setFilters(engineFilters); engineFiltersDlg.setVisible(true); } /* (non-Javadoc) * @see javax.swing.JComponent#setEnabled(boolean) */ @Override public void setEnabled(boolean enabled) { if (toolBar!=null) { toolBar.setEnabled(enabled); } if (navigationToolbar!=null) { navigationToolbar.setEnabled(enabled); } menuBar.setEnabled(enabled); super.setEnabled(enabled); } /** * @return The error browser dialog */ public ErrorBrowserDlg getErrorDialog() { if (errorBrowserDialog==null) { errorBrowserDialog=new ErrorBrowserDlg(this); } return errorBrowserDialog; } /** * * @return The jlog error dialog */ private ErrorLogDialog getJLogErroDialog() { if (errorDialog==null) { errorDialog = new ErrorLogDialog(logFrame,"jlog: Error log", false); } return errorDialog; } /** * Return {@link #logFrame}. * * * @return The logFrame * (it is <code>null</code> if jlog runs inside the OMC) */ public LogFrame getLogFrame() { return logFrame; } /** * Add a new error stack to the error browser dialog * * @param stackID The <code>STACKID</code> of the error trace in the tab */ public void addErrorTab(final String stackID) { Runnable runnable = new Runnable() { public void run() { getErrorDialog().addErrorTab(getLCModel1(),stackID); } }; Thread t = new Thread(runnable,"LoggingClient.addErrorTab"); t.setDaemon(true); t.start(); } /** * @return the zoom */ public ZoomManager getZoomManager() { return zoom; } /** * @return the toolBar */ public LogToolBar getToolBar() { return toolBar; } /** * @return the containerServices */ public ContainerServicesBase getContainerServices() { return containerServices; } /** * @return <code>true</code> if jlog runs in debug mode */ public boolean inDebugMode() { return debugMode; } /** * Show an error in the error panel displayed on top of the * table of logs. * <P> * Implementation notes: * <OL> * <LI>this method shows the error widget and set the * glass pane so that it will catch all the events but those directed * the error widget's ACK button. What this method does not do, is to * make the glass pane visible. This is done by the connection * listener methods. * If, in future, you want to show the glass pane even here, you should do * it explicitly. * <LI>when the connection with ACS is again available, the <code>acsLogConnEstablished</code> * programmatically pushes the ACS button of the error widget causing the widget * to disappear without any intervention from the user. * This is very useful when the auto reconnect option is enabled. * However, note that if <code>showErrorMessage</code> is used for notifying other * abnormal situations then a different strategy must be used to avoid the error * widget to disappear at the wrong time (i.e. without the user acknowledge the problem). * </OL> * <P> * <code>showErrorMessage</code> prints a message in the stderr too in case the glass pane * can't be made visible (for example if an error occurs while building the * <code>LoggingClient</code> object). * * @param shortDescription The description of the error * @param t The throwable that caused the error (can be <code>null</code>). * @return */ public void showErrorMessage(String shortDescription, Throwable t) { System.err.println("JLOG ERROR: "+shortDescription); if (t!=null) { t.printStackTrace(System.err); } if (t==null) { errorWidget.showMessage(MessageType.Error, shortDescription, null); } else { errorWidget.showMessage(shortDescription, t); } glassPane.setEventComponent(errorWidget.getAckButton()); toolBar.setEnabled(false); navigationToolbar.setEnabled(false); menuBar.setEnabled(false); } /** * When the user acknowledges the message, we enable the glass pane to forward all the * messages to the content pane. * <P> * This method is executed when the user presses over the ACK button of the * error widget and remove the constraints on the glass pane. * * @see <code>showErrorMessage</code> for further implementation details */ @Override public void errorAcknowledged() { glassPane.setEventComponent(null); toolBar.setEnabled(true); navigationToolbar.setEnabled(true); menuBar.setEnabled(true); } /** * Single ViewCoordinator instance, created on demand. */ private ViewCoordinator viewCoord; public ViewCoordinator getViewCoordinator() { if (viewCoord == null) { viewCoord = new ViewCoordinator(this, logEntryTable); } return viewCoord; } }