/** * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "Exolab" must not be used to endorse or promote * products derived from this Software without prior written * permission of Intalio, Inc. For written permission, * please contact info@exolab.org. * * 4. Products derived from this Software may not be called "Exolab" * nor may "Exolab" appear in their names without prior written * permission of Intalio, Inc. Exolab is a registered * trademark of Intalio, Inc. * * 5. Due credit should be given to the Exolab Project * (http://www.exolab.org/). * * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Intalio, Inc. All Rights Reserved. * * $Id$ */ package org.exolab.castor.gui; import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.WindowEvent; import java.io.FileReader; import java.io.FileWriter; import java.lang.reflect.Method; import java.util.Date; import java.util.Iterator; import java.util.Vector; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.JTextPane; import javax.swing.JToolBar; import javax.swing.UIManager; import javax.swing.table.DefaultTableModel; import org.exolab.castor.jdo.Database; import org.exolab.castor.jdo.JDOManager; import org.exolab.castor.jdo.OQLQuery; import org.exolab.castor.jdo.QueryResults; import org.exolab.castor.jdo.engine.OQLQueryImpl; import org.exolab.castor.mapping.Mapping; import org.exolab.castor.mapping.MappingException; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.Unmarshaller; /** * A simple Query tool. With this tool you can perform interactive * OQL Queries against a Castor Database. * * @author <a href="mauch@imkenberg.de">Thorsten Mauch</a> * @version $Revision$ $Date: 2005-12-13 14:58:48 -0700 (Tue, 13 Dec 2005) $ */ public final class QueryAnalyser { private boolean _packFrame = false; /** * Construct the application. */ private QueryAnalyser(final String databasename, final String dbconfig) { MainFrame frame = new MainFrame(databasename, dbconfig); //Validate frames that have preset sizes //Pack frames that have useful preferred size info, e.g. from their layout if (_packFrame) { frame.pack(); } else { frame.validate(); } //Center the window Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension frameSize = frame.getSize(); if (frameSize.height > screenSize.height) { frameSize.height = screenSize.height; } if (frameSize.width > screenSize.width) { frameSize.width = screenSize.width; } frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); frame.setVisible(true); } /** * Main method. */ public static void main(final String[] args) { if (args.length != 2) { System.out.println( "Usage: org.exolab.castor.tools.QueryAnalyser <Databasename> <Databaseconfig>"); System.out.println( "Example: org.exolab.castor.tools.QueryAnalyser testdb database.xml"); System.exit(1); } try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { e.printStackTrace(); } new QueryAnalyser(args[0], args[1]); } private class MainFrame extends JFrame { /** SerialVersionUID. */ private static final long serialVersionUID = 3524368558606642742L; private QueryHistory _qhistory = new QueryHistory(); private Mapping _mapping = new Mapping(); private JPanel _contentPane; private BorderLayout _borderLayout1 = new BorderLayout(); private DefaultTableModel _model; private JDOManager _jdo; private String _dbName; private String _dbConf; private JTabbedPane _tabbedPane = new JTabbedPane(); private JToolBar _toolbar = new JToolBar(); private JButton _btnNext = new JButton(); private JButton _btnExit = new JButton(); private JPanel _sqlresult = new JPanel(); private JTextPane _sqlPane = new JTextPane(); private BorderLayout _borderLayout3 = new BorderLayout(); private JTextPane _oqlquery = new JTextPane(); private JPanel _queryPanel = new JPanel(); private BorderLayout _borderLayout2 = new BorderLayout(); private JScrollPane _resultScrollpane = new JScrollPane(); private JTable _resultTable = new JTable(); private JButton _execute = new JButton(); private JScrollPane _errorScrollPane = new JScrollPane(); private JPanel _errorPanel = new JPanel(); private JTextPane _oqlerror = new JTextPane(); private BorderLayout _borderLayout4 = new BorderLayout(); private JButton _btnPrevious = new JButton(); private JLabel _statusBar = new JLabel(); /** * Construct the frame. */ public MainFrame(final String dbName, final String dbConf) { _dbName = dbName; _dbConf = dbConf; enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch (Exception e) { e.printStackTrace(); } } /** * Component initialization. */ private void jbInit() throws Exception { ClassLoader cl = ClassLoader.getSystemClassLoader(); //setIconImage(Toolkit.getDefaultToolkit().createImage( // testframe.class.getResource("[Your Icon]"))); _contentPane = (JPanel) this.getContentPane(); _contentPane.setLayout(_borderLayout1); this.setSize(new Dimension(600, 400)); this.setTitle("Castor OQL-Ouery Analyser"); //ResultScrollpane.setHorizontalScrollBarPolicy( // JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); //ResultScrollpane.setVerticalScrollBarPolicy( // JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); _sqlresult.setLayout(_borderLayout3); _oqlquery.setFont(new java.awt.Font("Dialog", 0, 12)); _oqlquery.setToolTipText("create Query here"); _queryPanel.setLayout(_borderLayout2); _resultScrollpane.setToolTipText(""); _resultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); _btnExit.setMaximumSize(new Dimension(50, 39)); _btnExit.setMinimumSize(new Dimension(50, 39)); _btnExit.setActionCommand(""); _btnExit.setIcon(new ImageIcon(cl.getResource( "org/exolab/castor/gui/images/exit.gif"))); _btnExit.setMnemonic('0'); _btnExit.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(final ActionEvent e) { exit(); } }); _execute.setMaximumSize(new Dimension(50, 39)); _execute.setMinimumSize(new Dimension(50, 39)); _execute.setActionCommand(""); _execute.setIcon(new ImageIcon(cl.getResource( "org/exolab/castor/gui/images/fire.gif"))); _execute.setMnemonic('0'); _execute.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(final ActionEvent e) { executeActionPerformed(e); } }); _errorPanel.setLayout(_borderLayout4); _btnPrevious.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(final ActionEvent e) { btnPreviousActionPerformed(e); } }); _btnNext.setMaximumSize(new Dimension(50, 39)); _btnNext.setMinimumSize(new Dimension(50, 39)); _btnNext.setActionCommand(""); _btnNext.setIcon(new ImageIcon(cl.getResource( "org/exolab/castor/gui/images/arrw04e.gif"))); _btnNext.setMnemonic('0'); _btnNext.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(final ActionEvent e) { btnNextActionPerformed(e); } }); _btnPrevious.setMaximumSize(new Dimension(50, 39)); _btnPrevious.setMinimumSize(new Dimension(50, 39)); _btnPrevious.setToolTipText("Goto previous Query"); _btnPrevious.setIcon(new ImageIcon(cl.getResource( "org/exolab/castor/gui/images/arrw04d.gif"))); _btnPrevious.setMnemonic('0'); _contentPane.add(_tabbedPane, BorderLayout.CENTER); _contentPane.add(_toolbar, BorderLayout.NORTH); _toolbar.add(_btnExit, null); _toolbar.add(_execute, null); _toolbar.add(_btnPrevious, null); _toolbar.add(_btnNext, null); _contentPane.add(_statusBar, BorderLayout.SOUTH); _tabbedPane.add(_queryPanel, "OQL Query"); _queryPanel.add(_oqlquery, BorderLayout.CENTER); _tabbedPane.add(_resultScrollpane, "Resultset"); _tabbedPane.add(_errorScrollPane, "Stacktrace"); _errorScrollPane.getViewport().add(_errorPanel, null); _errorPanel.add(_oqlerror, BorderLayout.CENTER); _tabbedPane.add(_sqlresult, "SQL"); _sqlresult.add(_sqlPane, BorderLayout.CENTER); _resultScrollpane.getViewport().add(_resultTable, null); // Open the Database openDB(); _statusBar.setText("Database " + _jdo.getDatabaseName() + " waiting for Queries"); // Load the query history loadHistory(); _oqlquery.setText(_qhistory.getCurrentQuery()); } /** * Overridden so we can exit when window is closed. */ protected void processWindowEvent(final WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { exit(); } } void executeActionPerformed(final ActionEvent e) { performQuery(); } public void performQuery() { OQLQuery oql; QueryResults r; boolean firstObject = true; Object o; Vector<Method> properties = null; _model = new DefaultTableModel(); try { _statusBar.setText("performing Query"); // clear results clearTabs(); //ResultScrollpane.getViewport().remove( // ResultScrollpane.getViewport().getComponent(0)); // create a new conec Database db = _jdo.getDatabase(); db.begin(); /** * add query to the history, * maybe it's important lo loglso querys that won't work * for this reason it's logged before creation */ _qhistory.addQuery(_oqlquery.getText()); oql = db.getOQLQuery(_oqlquery.getText()); // and execute it Date starttime = new Date(); r = oql.execute(Database.READONLY); Date endtime = new Date(); // write the status bar _statusBar.setText("Query successful, Time: " + (endtime.getTime() - starttime.getTime()) + " ms"); // get SQL statement via backdoor _sqlPane.setText(((OQLQueryImpl) oql).getSQL()); while (r.hasMore()) { o = r.next(); if (firstObject) { properties = getProperties(o); fillTableHeader(properties, _model); firstObject = false; } _model.addRow(fillRow(properties, o)); } db.commit(); _resultTable.setModel(_model); _resultTable.repaint(); _tabbedPane.setSelectedComponent(_resultScrollpane); } catch (Exception e) { // Print error into pane and status bar java.io.StringWriter sw = new java.io.StringWriter(); e.printStackTrace(new java.io.PrintWriter(sw)); _oqlerror.setText(sw.getBuffer().toString()); // focus to errortab _statusBar.setText(e.getMessage()); //TabbedPane.setSelectedComponent(ErrorScrollPane); } } private Vector<Method> getProperties(final Object o) { Vector<Method> properties = new Vector<Method>(); Method[] ms = o.getClass().getMethods(); Method m; for (int i = 0; i < ms.length; i++) { m = ms[i]; // if it begins with m and have no argument it is // a property if (m.getName().startsWith("get") && m.getParameterTypes().length == 0) { properties.add(m); } } return properties; } private void fillTableHeader( final Vector<Method> properties, final DefaultTableModel model) { Iterator<Method> i = properties.iterator(); Method m; while (i.hasNext()) { m = i.next(); model.addColumn(m.getName().substring(3)); } } private Vector<Object> fillRow(final Vector<Method> properties, final Object o) { Method m; Object temp; Vector<Object> results = new Vector<Object>(); Iterator<Method> i = properties.iterator(); while (i.hasNext()) { temp = null; m = i.next(); try { temp = m.invoke(o, (Object[]) null); } catch (Exception ie) { temp = null; } results.add(temp); } return results; } private void openDB() { try { JDOManager.loadConfiguration (_dbConf, ClassLoader.getSystemClassLoader()); _jdo = JDOManager.createInstance(_dbName); //only to try a connection _jdo.getDatabase(); } catch (MappingException pe) { pe.printStackTrace(); System.exit(1); } catch (org.exolab.castor.jdo.PersistenceException pe) { pe.printStackTrace(); System.exit(1); } } /** * Delete all content in the tabbed pane. */ private void clearTabs() { _oqlerror.setText(""); _sqlPane.setText(""); _resultTable.setModel(new DefaultTableModel()); } void btnPreviousActionPerformed(final ActionEvent e) { clearTabs(); _oqlquery.setText(_qhistory.getPreviousQuery()); _tabbedPane.setSelectedComponent(_queryPanel); } void btnNextActionPerformed(final ActionEvent e) { clearTabs(); _oqlquery.setText(_qhistory.getNextQuery()); _tabbedPane.setSelectedComponent(_queryPanel); } public void saveHistory() { // write back the history to file try { FileWriter writer = new FileWriter("queryhistory.xml"); Marshaller marshaller = new Marshaller(writer); marshaller.setMapping(_mapping); marshaller.marshal(_qhistory); } catch (Exception e) { e.printStackTrace(); } } private void loadHistory() { try { Unmarshaller unmarshaller = new Unmarshaller( Class.forName("org.exolab.castor.gui.QueryHistory")); ClassLoader cl = ClassLoader.getSystemClassLoader(); _mapping.loadMapping(cl.getResource("org/exolab/castor/gui/Queryanlyser.xml")); unmarshaller.setMapping(_mapping); FileReader reader = new FileReader("queryhistory.xml"); _qhistory = (QueryHistory) unmarshaller.unmarshal(reader); } catch (Exception e) { e.printStackTrace(); // if there is no file, it's ok also // then we have an empty History } } void exit() { saveHistory(); System.exit(0); } } }