/*
* 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;
}
}