001: /*
002: * Copyright (C) The Apache Software Foundation. All rights reserved.
003: *
004: * This software is published under the terms of the Apache Software
005: * License version 1.1, a copy of which has been included with this
006: * distribution in the APACHE.txt file. */
007: package org.jahia.sqlprofiler.gui;
008:
009: import java.awt.BorderLayout;
010: import java.awt.Dimension;
011: import java.awt.event.WindowAdapter;
012: import java.awt.event.WindowEvent;
013: import java.io.IOException;
014: import java.util.Properties;
015: import javax.swing.BorderFactory;
016: import javax.swing.JFrame;
017: import javax.swing.JMenu;
018: import javax.swing.JMenuBar;
019: import javax.swing.JMenuItem;
020: import javax.swing.JOptionPane;
021: import javax.swing.JPanel;
022: import javax.swing.JScrollPane;
023: import javax.swing.JSplitPane;
024: import javax.swing.JTable;
025: import javax.swing.ListSelectionModel;
026: import javax.swing.UIManager;
027: import org.apache.log4j.Category;
028: import org.apache.log4j.PropertyConfigurator;
029: import javax.swing.*;
030: import java.awt.FlowLayout;
031: import java.awt.Paint;
032: import java.awt.Color;
033: import org.jCharts.properties.PieChart2DProperties;
034: import org.jCharts.chartData.PieChartDataSet;
035: import org.jCharts.nonAxisChart.PieChart2D;
036: import org.jCharts.properties.LegendProperties;
037: import org.jCharts.properties.ChartProperties;
038: import java.awt.Graphics2D;
039:
040: /**
041: * The main application.
042: *
043: * @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a>
044: *
045: * 11/14/2003 : Add DML statements by Jean-Philippe VALENTIN (JPV) version 0.3
046: */
047: public class Main extends JFrame {
048: /** the default port number to listen on **/
049: private static final int DEFAULT_PORT = 4445;
050:
051: /** name of property for port name **/
052: public static final String PORT_PROP_NAME = "chainsaw.port";
053:
054: /** use to log messages **/
055: private static final Category LOG = Category
056: .getInstance(Main.class);
057:
058: /**
059: * Creates a new <code>Main</code> instance.
060: */
061: private Main() {
062: super ("SQL Profiler v0.3"); //JPV : change version 0.2 to 0.3
063:
064: // First let's use the system's default look and feel
065: try {
066: UIManager.setLookAndFeel(UIManager
067: .getSystemLookAndFeelClassName());
068: } catch (UnsupportedLookAndFeelException ulafe) {
069: LOG.error("Unsupported look & feel : ", ulafe);
070: } catch (IllegalAccessException iae) {
071: LOG.error("Illegal access exception : ", iae);
072: } catch (InstantiationException ie) {
073: LOG.error("Error : ", ie);
074: } catch (ClassNotFoundException cnfe) {
075: LOG.error("Error : ", cnfe);
076: }
077:
078: // create the all important model
079: final LoggerTableModel loggerModel = new LoggerTableModel();
080: final ProfileStatementTableModel profileStatementTableModel = new ProfileStatementTableModel(
081: loggerModel);
082: loggerModel
083: .setProfileStatementModel(profileStatementTableModel);
084:
085: //Create the menu bar.
086: final JMenuBar menuBar = new JMenuBar();
087: setJMenuBar(menuBar);
088: final JMenu menu = new JMenu("File");
089: menuBar.add(menu);
090:
091: /*
092: try {
093: final LoadXMLAction lxa = new LoadXMLAction(this, loggerModel);
094: final JMenuItem loadMenuItem = new JMenuItem("Load Log4J XML file...");
095: menu.add(loadMenuItem);
096: loadMenuItem.addActionListener(lxa);
097: } catch (NoClassDefFoundError e) {
098: LOG.info("Missing classes for XML parser", e);
099: JOptionPane.showMessageDialog(
100: this,
101: "XML parser not in classpath - unable to load XML events.",
102: "CHAINSAW",
103: JOptionPane.ERROR_MESSAGE);
104: } catch (Exception e) {
105: LOG.info("Unable to create the action to load XML files", e);
106: JOptionPane.showMessageDialog(
107: this,
108: "Unable to create a XML parser - unable to load XML events.",
109: "CHAINSAW",
110: JOptionPane.ERROR_MESSAGE);
111: }
112: */
113:
114: final JMenuItem exitMenuItem = new JMenuItem("Exit");
115: menu.add(exitMenuItem);
116: exitMenuItem.addActionListener(ExitAction.INSTANCE);
117:
118: final MainTabbedPanel mainTabbedPanel = new MainTabbedPanel();
119:
120: final JPanel loggerPanel = new JPanel(new BorderLayout());
121: final JPanel profilerPanel = new JPanel(new BorderLayout());
122: final JPanel analysisPanel = new JPanel(new BorderLayout());
123:
124: final ToolbarPanel toolbarPanel = new ToolbarPanel(loggerModel,
125: profileStatementTableModel);
126: getContentPane().add(toolbarPanel, BorderLayout.NORTH);
127:
128: buildLoggerPanel(loggerModel, loggerPanel);
129:
130: buildProfilePanel(profileStatementTableModel, profilerPanel);
131:
132: buildAnalysisPanel(loggerModel, profileStatementTableModel,
133: analysisPanel);
134:
135: mainTabbedPanel.addTab("Profiler", profilerPanel,
136: "SQL Profiler");
137: mainTabbedPanel.addTab("Logger", loggerPanel, "Logging view");
138: mainTabbedPanel.addTab("Analysis", analysisPanel,
139: "Analysis view");
140: mainTabbedPanel.finishTabs();
141: getContentPane().add(mainTabbedPanel, BorderLayout.CENTER);
142:
143: addWindowListener(new WindowAdapter() {
144: public void windowClosing(WindowEvent aEvent) {
145: ExitAction.INSTANCE.actionPerformed(null);
146: }
147: });
148:
149: Box statusBar = Box.createHorizontalBox();
150: JPanel messagePanel = new JPanel(new FlowLayout(
151: FlowLayout.LEFT, 0, 0));
152: messagePanel
153: .setBorder(BorderFactory.createLoweredBevelBorder());
154: JLabel messageTextLabel = new JLabel();
155: messageTextLabel.setHorizontalAlignment(JLabel.LEFT);
156: messageTextLabel.setText("Not connected to P6Spy");
157: messagePanel.add(messageTextLabel);
158: statusBar.add(messagePanel);
159: /*
160: JPanel progressPanel = new JPanel(new BorderLayout());
161: progressPanel.setBorder(BorderFactory.createLoweredBevelBorder());
162: JProgressBar progressBar = new JProgressBar();
163: progressBar.setValue(0);
164: progressPanel.add(progressBar, BorderLayout.CENTER);
165: statusBar.add(progressPanel);
166: */
167: Box statusLabelBox = Box.createHorizontalBox();
168: StatusLabel statusLabel = new StatusLabel();
169: statusLabelBox.add(statusLabel);
170: statusBar.add(statusLabelBox);
171: getContentPane().add(statusBar, BorderLayout.SOUTH);
172:
173: pack();
174: setVisible(true);
175:
176: setupReceiver(loggerModel, statusLabel, messageTextLabel);
177: }
178:
179: private void buildProfilePanel(
180: ProfileStatementTableModel profileStatementTableModel,
181: JPanel profilerPanel) {
182: // Create the table
183: final JTable profileStatementTable = new JTable(
184: profileStatementTableModel);
185: profileStatementTableModel
186: .addMouseListenerToHeaderInTable(profileStatementTable);
187: profileStatementTable
188: .setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
189: profileStatementTable.getColumnModel().getColumn(0)
190: .setMinWidth(120);
191: profileStatementTable.getColumnModel().getColumn(1)
192: .setMaxWidth(70);
193: profileStatementTable.getColumnModel().getColumn(2)
194: .setMaxWidth(30);
195: profileStatementTable.getColumnModel().getColumn(3)
196: .setPreferredWidth(70);
197: profileStatementTable.getColumnModel().getColumn(4)
198: .setPreferredWidth(70);
199: profileStatementTable.getColumnModel().getColumn(5)
200: .setPreferredWidth(680 - 70 - 70 - 30 - 70 - 150);
201: final JScrollPane profileScrollPane = new JScrollPane(
202: profileStatementTable);
203: profileScrollPane.setBorder(BorderFactory
204: .createTitledBorder("SQL Statements: "));
205: profileScrollPane.setPreferredSize(new Dimension(700, 150));
206:
207: ProfileResultTableModel profileResultModel = new ProfileResultTableModel();
208: profileStatementTableModel
209: .setProfileResultModel(profileResultModel);
210: final JTable profileResultTable = new JTable(profileResultModel);
211: profileResultModel
212: .addMouseListenerToHeaderInTable(profileResultTable);
213: profileResultTable
214: .setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
215: profileResultTable.getColumnModel().getColumn(0)
216: .setMaxWidth(50);
217: profileResultTable.getColumnModel().getColumn(1)
218: .setMaxWidth(70);
219: profileResultTable.getColumnModel().getColumn(2)
220: .setMaxWidth(70);
221: profileResultTable.getColumnModel().getColumn(3)
222: .setPreferredWidth(160);
223: profileResultTable.getColumnModel().getColumn(4)
224: .setPreferredWidth(680 - 160 - 70 - 70 - 50);
225: final JScrollPane profileResultScrollPane = new JScrollPane(
226: profileResultTable);
227: profileResultScrollPane.setBorder(BorderFactory
228: .createTitledBorder("Profile results: "));
229: profileResultScrollPane
230: .setPreferredSize(new Dimension(700, 150));
231:
232: Box counterBox = Box.createHorizontalBox();
233:
234: JLabel statementCountTextLabel = new JLabel(
235: " Total statements : ");
236: counterBox.add(statementCountTextLabel);
237: JLabel statementCountValueLabel = new JLabel("0");
238: profileStatementTableModel
239: .setStatementCountValueLabel(statementCountValueLabel);
240: counterBox.add(statementCountValueLabel);
241: counterBox.add(Box.createHorizontalStrut(10));
242: JLabel statementTimeTextLabel = new JLabel(
243: " Total statement time [ms] : ");
244: counterBox.add(statementTimeTextLabel);
245: JLabel statementTimeValueLabel = new JLabel("0");
246: profileStatementTableModel
247: .setStatementTimeValueLabel(statementTimeValueLabel);
248: counterBox.add(statementTimeValueLabel);
249:
250: profilerPanel.add(counterBox, BorderLayout.NORTH);
251:
252: // Create the details
253: final JPanel profileDetails = new ProfileDetailsPanel(
254: profileStatementTable, profileStatementTableModel);
255: profileDetails.setPreferredSize(new Dimension(700, 150));
256:
257: final JSplitPane profileSplitPane = new JSplitPane(
258: JSplitPane.VERTICAL_SPLIT, profileScrollPane,
259: profileResultScrollPane);
260:
261: final JSplitPane profileSplitPane2 = new JSplitPane(
262: JSplitPane.VERTICAL_SPLIT, profileSplitPane,
263: profileDetails);
264:
265: profilerPanel.add(profileSplitPane2, BorderLayout.CENTER);
266:
267: }
268:
269: private void buildLoggerPanel(LoggerTableModel loggerModel,
270: JPanel loggerPanel) {
271: // Add control panel
272: final ControlPanel cp = new ControlPanel(loggerModel);
273: loggerPanel.add(cp, BorderLayout.NORTH);
274:
275: // Create the table
276: final JTable loggerTable = new JTable(loggerModel);
277: loggerTable
278: .setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
279: final JScrollPane loggerScrollPane = new JScrollPane(
280: loggerTable);
281: loggerScrollPane.setBorder(BorderFactory
282: .createTitledBorder("Events: "));
283: loggerScrollPane.setPreferredSize(new Dimension(700, 150));
284:
285: // Create the details
286: final JPanel loggerDetails = new DetailPanel(loggerTable,
287: loggerModel);
288: loggerDetails.setPreferredSize(new Dimension(700, 150));
289:
290: // Add the table and stack trace into a splitter
291: final JSplitPane loggerSplitPane = new JSplitPane(
292: JSplitPane.VERTICAL_SPLIT, loggerScrollPane,
293: loggerDetails);
294: loggerPanel.add(loggerSplitPane, BorderLayout.CENTER);
295: }
296:
297: private void buildAnalysisPanel(LoggerTableModel loggerModel,
298: ProfileStatementTableModel profileStatementModel,
299: JPanel analysisPanel) {
300:
301: try {
302: QueryCountChartModel queryCountChartModel = new QueryCountChartModel(
303: profileStatementModel);
304: ChartPanel queryCountChartPanel = new ChartPanel(
305: queryCountChartModel);
306: loggerModel.setQueryCountChartModel(queryCountChartModel);
307: queryCountChartPanel.setPreferredSize(new Dimension(700,
308: 150));
309:
310: QueryTrafficChartModel queryTrafficChartModel = new QueryTrafficChartModel(
311: profileStatementModel);
312: ChartPanel queryTrafficChartPanel = new ChartPanel(
313: queryTrafficChartModel);
314: loggerModel
315: .setQueryTrafficChartModel(queryTrafficChartModel);
316: queryTrafficChartPanel.setPreferredSize(new Dimension(700,
317: 150));
318:
319: final JSplitPane analysisSplitPane = new JSplitPane(
320: JSplitPane.VERTICAL_SPLIT, queryCountChartPanel,
321: queryTrafficChartPanel);
322:
323: analysisPanel.add(analysisSplitPane, BorderLayout.CENTER);
324:
325: } catch (Throwable t) {
326: LOG.error("Error while creating chart panel", t);
327: }
328:
329: }
330:
331: /**
332: * Setup recieving messages.
333: *
334: * @param aModel a <code>MyTableModel</code> value
335: */
336: private void setupReceiver(final LoggerTableModel aModel,
337: final StatusLabel statusLabel, final JLabel messageTextLabel) {
338: int port = DEFAULT_PORT;
339: final String strRep = System.getProperty(PORT_PROP_NAME);
340: if (strRep != null) {
341: try {
342: port = Integer.parseInt(strRep);
343: } catch (NumberFormatException nfe) {
344: LOG.fatal("Unable to parse " + PORT_PROP_NAME
345: + " property with value " + strRep + ".");
346: JOptionPane.showMessageDialog(this ,
347: "Unable to parse port number from '" + strRep
348: + "', quitting.", "CHAINSAW",
349: JOptionPane.ERROR_MESSAGE);
350: System.exit(1);
351: }
352: }
353:
354: try {
355: final LoggingReceiver lr = new LoggingReceiver(aModel, port);
356: lr.addLogReceptionListener(new LogReceptionAdapter() {
357: public void logReceptionConnected(
358: LogReceptionEvent logReceptionEvent) {
359: statusLabel.setStatusActivated(true);
360: messageTextLabel.setText("Connected to P6Spy");
361: }
362:
363: public void logReceptionDisconnected(
364: LogReceptionEvent logReceptionEvent) {
365: statusLabel.setStatusActivated(false);
366: messageTextLabel.setText("Disconnected from P6Spy");
367: }
368:
369: public void logReceptionDataReceived(
370: LogReceptionEvent logReceptionEvent) {
371: aModel
372: .addEvent(logReceptionEvent
373: .getEventDetails());
374: }
375: });
376:
377: lr.start();
378: } catch (IOException e) {
379: LOG.fatal("Unable to connect to socket server, quiting", e);
380: JOptionPane.showMessageDialog(this ,
381: "Unable to create socket on port " + port
382: + ", quitting.", "CHAINSAW",
383: JOptionPane.ERROR_MESSAGE);
384: System.exit(1);
385: }
386: }
387:
388: ////////////////////////////////////////////////////////////////////////////
389: // static methods
390: ////////////////////////////////////////////////////////////////////////////
391:
392: /** initialise log4j **/
393: private static void initLog4J() {
394: final Properties props = new Properties();
395: props.setProperty("log4j.rootCategory", "DEBUG, A1");
396: props.setProperty("log4j.appender.A1",
397: "org.apache.log4j.ConsoleAppender");
398: props.setProperty("log4j.appender.A1.layout",
399: "org.apache.log4j.TTCCLayout");
400: PropertyConfigurator.configure(props);
401: }
402:
403: /**
404: * The main method.
405: *
406: * @param aArgs ignored
407: */
408: public static void main(String[] aArgs) {
409: initLog4J();
410: new Main();
411: }
412: }
|