All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.squirrel_sql.client.gui.ViewLogsSheet Maven / Gradle / Ivy

package net.sourceforge.squirrel_sql.client.gui;

/*
 * Copyright (C) 2002-2006 Colin Bell
 * [email protected]
 *
 * 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
 */
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

import net.sourceforge.squirrel_sql.client.IApplication;
import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.DialogWidget;
import net.sourceforge.squirrel_sql.client.preferences.SquirrelPreferences;
import net.sourceforge.squirrel_sql.client.util.ApplicationFiles;
import net.sourceforge.squirrel_sql.fw.gui.CursorChanger;
import net.sourceforge.squirrel_sql.fw.gui.DirectoryListComboBox;
import net.sourceforge.squirrel_sql.fw.gui.GUIUtils;
import net.sourceforge.squirrel_sql.fw.gui.TextPopupMenu;
import net.sourceforge.squirrel_sql.fw.gui.ToolBar;
import net.sourceforge.squirrel_sql.fw.util.StringManager;
import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;

/**
 * This sheet shows the SQuirreL log files.
 * 
 * @author Colin Bell
 */
public class ViewLogsSheet extends DialogWidget
{
	/** Internationalized strings for this class. */
	private static final StringManager s_stringMgr =
		StringManagerFactory.getStringManager(ViewLogsSheet.class);

	/** Logger for this class. */
	private static final ILogger s_log = LoggerController.createLogger(ViewLogsSheet.class);

	/** Singleton instance of this class. */
	private static ViewLogsSheet s_instance;

	/** Application API. */
	private final IApplication _app;

	/** Preferences */
	private final SquirrelPreferences _prefs;

	/** Combo box containing all the log files. */
	private final LogsComboBox _logDirCmb = new LogsComboBox();

	/** Text area containing the log contents. */
	private final JTextArea _logContentsTxt = new JTextArea(20, 50);

	/** Button that refreshes the log contents. */
	private final JButton _refreshBtn = new JButton(s_stringMgr.getString("ViewLogsSheet.refresh"));

	private final JCheckBox _errorChkbox = new JCheckBox("Errors");

	private final JCheckBox _debugChkbox = new JCheckBox("Debug");

	private final JCheckBox _infoChkbox = new JCheckBox("Info");

	/** Directory containing the log files. */
	private final File _logDir;

	/** If true user is closing this window. */
	private boolean _closing = false;

	/** If true log is being refreshed. */
	private boolean _refreshing = false;

	/**
	 * Ctor specifying the application API.
	 * 
	 * @param app
	 *           Application API.
	 * @throws IllegalArgumentException
	 *            Thrown if a null IApplication passed.
	 */
	private ViewLogsSheet(IApplication app)
	{
		super(s_stringMgr.getString("ViewLogsSheet.title"), true, true, true, true, app);
		if (app == null) { throw new IllegalArgumentException("IApplication == null"); }

		_app = app;
		_prefs = _app.getSquirrelPreferences();
		_logDir = new ApplicationFiles().getExecutionLogFile().getParentFile();
		createUserInterface();
	}

	/**
	 * Show this window
	 * 
	 * @param app
	 *           Application API.
	 * @throws IllegalArgumentException
	 *            Thrown if a null IApplication object passed.
	 */
	public static synchronized void showSheet(IApplication app)
	{
		if (s_instance == null)
		{
			s_instance = new ViewLogsSheet(app);
			app.getMainFrame().addWidget(s_instance);
			centerWithinDesktop(s_instance);
		}

		final boolean wasVisible = s_instance.isVisible();
		if (!wasVisible)
		{
			s_instance.setVisible(true);
		}
		s_instance.moveToFront();
		if (!wasVisible && !s_instance._refreshing)
		{
			s_instance.startRefreshingLog();
		}
	}

	/**
	 * Nulls the singleton instance of this class in a thread-safe way.
	 */
	public static synchronized void disposeInstance()
	{
		s_instance = null;
	}

	@Override
	public void dispose()
	{
		// Stop refresh if it is running.
		_closing = true;

		ViewLogsSheet.disposeInstance();

		super.dispose();
	}

	/**
	 * Close this sheet.
	 */
	private void performClose()
	{
		dispose();
	}

	/**
	 * Start a thread to refrsh the log.
	 */
	private synchronized void startRefreshingLog()
	{
		if (!_refreshing)
		{
			_app.getThreadPool().addTask(new Refresher());
		}
	}

	/**
	 * Enables the log combo box and refresh button using the Swing event thread.
	 */
	private void enableComponents(final boolean enabled)
	{
		GUIUtils.processOnSwingEventThread(new Runnable()
		{
			public void run()
			{
				_refreshBtn.setEnabled(enabled);
				_logDirCmb.setEnabled(enabled);
			}
		});
	}

	/**
	 * Refresh the log.
	 */
	private void refreshLog()
	{
		enableComponents(false);
		final CursorChanger cursorChg = new CursorChanger(getAwtContainer());
		cursorChg.show();
		try
		{
			try
			{
				SwingUtilities.invokeAndWait(new Runnable()
				{
					public void run()
					{
						_logContentsTxt.setText("");
					}
				});
			}
			catch (final Exception ex)
			{
				// i18n[ViewLogsSheet.error.clearlogcontents=Error clearing the log contents]
				s_log.error(s_stringMgr.getString("ViewLogsSheet.error.clearlogcontents"), ex);
			}
			final File logFile = (File) _logDirCmb.getSelectedItem();
			if (logFile != null)
			{
				try
				{
					if (logFile.exists() && logFile.canRead())
					{
						final BufferedReader rdr = new BufferedReader(new FileReader(logFile));
						try
						{
							String line = null;
							StringBuilder chunk = new StringBuilder(16384);
							while ((line = rdr.readLine()) != null)
							{
								if (_closing) { return; }

								if (chunk.length() > 16000)
								{
									final String finalLine = chunk.toString();
									SwingUtilities.invokeAndWait(new Runnable()
									{
										public void run()
										{
											if (!_closing)
											{
												_logContentsTxt.append(finalLine);
											}
										}
									});
									chunk = new StringBuilder(16384);
								}
								else
								{
									if (shouldAppendLineToChunk(line))
									{
										chunk.append(line).append('\n');
									}
								}
							}

							if (_closing) { return; }

							final String finalLine = chunk.toString();
							SwingUtilities.invokeAndWait(new Runnable()
							{
								public void run()
								{
									if (!_closing)
									{
										_logContentsTxt.append(finalLine);
									}
								}
							});
						}
						finally
						{
							rdr.close();
						}
					}
				}
				catch (final Exception ex)
				{
					// i18n[ViewLogsSheet.error.processinglogfile=Error occured processing log file]
					final String msg = s_stringMgr.getString("ViewLogsSheet.error.processinglogfile");
					s_log.error(msg, ex);
				}
			}
			else
			{
				if (s_log.isDebugEnabled()) {
					// i18n[ViewLogsSheet.info.nulllogfile=Null log file name]
					s_log.debug(s_stringMgr.getString("ViewLogsSheet.info.nulllogfile"));
				}
			}

			if (_closing) { return; }

			// Position to the start of the last line in log.
			try
			{
				final int pos = Math.max(0, _logContentsTxt.getText().length() - 1);
				final int line = _logContentsTxt.getLineOfOffset(pos);
				final int finalpos = _logContentsTxt.getLineStartOffset(line);
				SwingUtilities.invokeAndWait(new Runnable()
				{
					public void run()
					{
						_logContentsTxt.setCaretPosition(finalpos);
					}
				});
			}
			catch (final Exception ex)
			{
				// i18n[ViewLogsSheet.error.setcaret=Error positioning caret in log text component]
				s_log.error(s_stringMgr.getString("ViewLogsSheet.error.setcaret"), ex);
			}
		}
		finally
		{
			enableComponents(true);
			_refreshing = false;
			cursorChg.restore();
		}
	}

	/**
	 * 199828 [Foo Thread] message
	 * 
	 * @param line
	 * @return
	 */
	private boolean shouldAppendLineToChunk(String line)
	{
		boolean result = false;
		if (line == null || line.length() == 0) { return false; }
		if (_errorChkbox.isSelected() && _debugChkbox.isSelected() && _infoChkbox.isSelected()) { return true; }
		final int threadNameEndIdx = line.indexOf("]");
		if (threadNameEndIdx > -1)
		{
			char levelChar = ' ';
			if (line.length() >= threadNameEndIdx + 2)
			{
				levelChar = line.charAt(threadNameEndIdx + 2);
			}
			if (_errorChkbox.isSelected() && levelChar == 'E')
			{
				result = true;
			}
			if (_debugChkbox.isSelected() && levelChar == 'D')
			{
				result = true;
			}
			if (_infoChkbox.isSelected() && levelChar == 'I')
			{
				result = true;
			}
			if (levelChar != 'E' && levelChar != 'D' && levelChar != 'I')
			{
				result = true;
			}
		}
		else
		{
			result = true;
		}
		return result;
	}

	/**
	 * Create user interface.
	 */
	private void createUserInterface()
	{
		setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		makeToolWindow(true);
		final Container contentPane = getContentPane();
		contentPane.setLayout(new BorderLayout());
		contentPane.add(createToolBar(), BorderLayout.NORTH);
		contentPane.add(createMainPanel(), BorderLayout.CENTER);
		contentPane.add(createButtonsPanel(), BorderLayout.SOUTH);
		pack();

		final AbstractAction closeAction = new AbstractAction()
		{
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent actionEvent)
			{
				performClose();
			}
		};
		final KeyStroke escapeStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
		getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(escapeStroke,
			"CloseAction");
		getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escapeStroke, "CloseAction");
		getRootPane().getInputMap(JComponent.WHEN_FOCUSED).put(escapeStroke, "CloseAction");
		getRootPane().getActionMap().put("CloseAction", closeAction);

	}

	private ToolBar createToolBar()
	{
		final ToolBar tb = new ToolBar();
		tb.setUseRolloverButtons(true);
		tb.setFloatable(false);

		final Object[] args = { getTitle(), _logDir.getAbsolutePath() };
		final String lblTitle = s_stringMgr.getString("ViewLogsSheet.storedin", args);
		final JLabel lbl = new JLabel(lblTitle);
		lbl.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
		tb.add(lbl);

		return tb;
	}

	/**
	 * Create the main panel containing the log details and selector.
	 */
	private JPanel createMainPanel()
	{
		// _logContentsTxt.setEditable(false);
		final TextPopupMenu pop = new TextPopupMenu();
		pop.setTextComponent(_logContentsTxt);
		_logContentsTxt.addMouseListener(new MouseAdapter()
		{
			@Override
			public void mousePressed(MouseEvent evt)
			{
				if (evt.isPopupTrigger())
				{
					pop.show(evt.getComponent(), evt.getX(), evt.getY());
				}
			}

			@Override
			public void mouseReleased(MouseEvent evt)
			{
				if (evt.isPopupTrigger())
				{
					pop.show(evt.getComponent(), evt.getX(), evt.getY());
				}
			}
		});

		final File appLogFile = new ApplicationFiles().getExecutionLogFile();
		_logDirCmb.load(appLogFile.getParentFile());

		if (_logDirCmb.getModel().getSize() > 0)
		{
			LogFile logFile = new LogFile(appLogFile);
			_logDirCmb.setSelectedItem(logFile);
		}

		// Done after the set of the selected item above so that we control
		// when the initial build is done. We want to make sure that under all
		// versions of the JDK that the window is shown before the (possibly
		// lengthy) refresh starts.
		_logDirCmb.addActionListener(new ChangeLogListener());

		final JPanel pnl = new JPanel(new BorderLayout());
		pnl.add(_logDirCmb, BorderLayout.NORTH);
		_logContentsTxt.setBorder(BorderFactory.createEmptyBorder(0, 1, 0, 0));
		pnl.add(new JScrollPane(_logContentsTxt), BorderLayout.CENTER);

		return pnl;
	}

	/**
	 * Create panel at bottom containing the buttons.
	 */
	private JPanel createButtonsPanel()
	{
		final JPanel pnl = new JPanel();

		pnl.add(_refreshBtn);
		_refreshBtn.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent evt)
			{
				startRefreshingLog();
			}
		});

		final JButton closeBtn = new JButton(s_stringMgr.getString("ViewLogsSheet.close"));
		closeBtn.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent evt)
			{
				performClose();
			}
		});
		pnl.add(closeBtn);

		_errorChkbox.setSelected(_prefs.getShowErrorLogMessages());
		_errorChkbox.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				_prefs.setShowErrorLogMessages(_errorChkbox.isSelected());
			}
		});
		_infoChkbox.setSelected(_prefs.getShowInfoLogMessages());
		_infoChkbox.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				_prefs.setShowInfoLogMessages(_infoChkbox.isSelected());
			}
		});
		_debugChkbox.setSelected(_prefs.getShowDebugLogMessage());
		_debugChkbox.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				_prefs.setShowDebugLogMessages(_debugChkbox.isSelected());
			}
		});
		pnl.add(_errorChkbox);
		pnl.add(_infoChkbox);
		pnl.add(_debugChkbox);

		GUIUtils.setJButtonSizesTheSame(new JButton[] { closeBtn, _refreshBtn });
		getRootPane().setDefaultButton(closeBtn);

		return pnl;
	}

	private final class ChangeLogListener implements ActionListener
	{
		public void actionPerformed(ActionEvent evt)
		{
			ViewLogsSheet.this.startRefreshingLog();
		}
	}

	private final class Refresher implements Runnable
	{
		public void run()
		{
			ViewLogsSheet.this.refreshLog();
		}
	}

	private static final class LogsComboBox extends DirectoryListComboBox
	{
		private static final long serialVersionUID = 1L;

		private File _dir;

		@Override
		public void load(File dir, FilenameFilter filter)
		{
			_dir = dir;
			super.load(dir, filter);
		}

		@Override
		public void addItem(Object anObject)
		{
			super.addItem(new LogFile(_dir, anObject.toString()));
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy