From e1093ad3772b77e904245b679924df885f951c30 Mon Sep 17 00:00:00 2001 From: Chrriis Date: Tue, 1 May 2012 20:47:33 +0200 Subject: [PATCH 1/2] [#1177] Add SQL Console module to jOOQ - Statement filtering is implemented and exposed in UI. --- .../java/org/jooq/debug/StatementMatcher.java | 144 +++++----------- .../org/jooq/debug/console/LoggerPane.java | 24 +++ .../console/StatementMatcherDialogBox.java | 109 ++++++++++++ .../debug/console/StatementMatcherPane.java | 157 ++++++++++++++++++ .../debug/console/StatementMatchersPane.java | 128 ++++++++++++++ .../jooq/debug/console/TextMatcherPane.java | 78 +++++++++ .../jooq/debug/console/misc/TextMatcher.java | 150 +++++++++++++++++ .../debug/console/resources/FilterOff16.png | Bin 0 -> 3678 bytes .../debug/console/resources/FilterOn16.png | Bin 0 -> 344 bytes 9 files changed, 685 insertions(+), 105 deletions(-) create mode 100644 jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherDialogBox.java create mode 100644 jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherPane.java create mode 100644 jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatchersPane.java create mode 100644 jOOQ-console/src/main/java/org/jooq/debug/console/TextMatcherPane.java create mode 100644 jOOQ-console/src/main/java/org/jooq/debug/console/misc/TextMatcher.java create mode 100644 jOOQ-console/src/main/resources/org/jooq/debug/console/resources/FilterOff16.png create mode 100644 jOOQ-console/src/main/resources/org/jooq/debug/console/resources/FilterOn16.png diff --git a/jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java b/jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java index 2c5423f51d..5a3cde522c 100644 --- a/jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java +++ b/jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java @@ -39,135 +39,69 @@ package org.jooq.debug; import java.io.Serializable; import java.util.EnumSet; import java.util.Set; -import java.util.regex.Pattern; + +import org.jooq.debug.console.misc.TextMatcher; @SuppressWarnings("serial") public class StatementMatcher implements Serializable { - public static enum TextMatchingType { - STARTS_WITH, - CONTAINS, - EQUALS, - MATCHES_REG_EXP, - } - - private String threadName; - private TextMatchingType textMatchingType; - private String text; - private boolean isTextMatchingCaseSensitive; + private boolean isActive; + private TextMatcher threadNameTextMatcher; + private TextMatcher statementTextMatcher; private Set queryTypeSet; - private Pattern pattern; - /** - * @param threadName a name or null for no matching on thread name. - * @param textMatchingType a type or null for no text matching. + * @param threadNameTextMatcher a text matcher for thread name or null for no text matching. + * @param statementTextMatcher a text matcher for statement or null for no text matching. * @param queryTypeSet some types or null for all types. */ - public StatementMatcher(String threadName, TextMatchingType textMatchingType, String text, boolean isTextMatchingCaseSensitive, Set queryTypeSet) { - this.threadName = threadName; - this.textMatchingType = textMatchingType; - this.text = text; - this.isTextMatchingCaseSensitive = isTextMatchingCaseSensitive; + public StatementMatcher(TextMatcher threadNameTextMatcher, TextMatcher statementTextMatcher, Set queryTypeSet, boolean isActive) { + this.threadNameTextMatcher = threadNameTextMatcher; + this.statementTextMatcher = statementTextMatcher; this.queryTypeSet = queryTypeSet == null? null: EnumSet.copyOf(queryTypeSet); - switch (textMatchingType) { - case CONTAINS: { - String patternText = ".*\\Q" + text.replace("\\E", "\\\\E").replace("\\Q", "\\\\Q") + "\\E.*\\Q"; - pattern = Pattern.compile(patternText, isTextMatchingCaseSensitive? 0: Pattern.CASE_INSENSITIVE); - break; - } - case MATCHES_REG_EXP: { - pattern = Pattern.compile(text, isTextMatchingCaseSensitive? 0: Pattern.CASE_INSENSITIVE); - break; - } - } + this.isActive = isActive; } public boolean matches(StatementInfo statementInfo) { - if(threadName != null) { - if(!threadName.equals(statementInfo.getThreadName())) { - return false; - } + if(!isActive) { + return false; } - if(textMatchingType != null) { - if(text == null) { + boolean hasMatcher = false; + if(threadNameTextMatcher != null) { + if(!threadNameTextMatcher.matches(statementInfo.getThreadName())) { return false; } - switch(textMatchingType) { - case STARTS_WITH: { - boolean isMatching = false; - for(String sql: statementInfo.getQueries()) { - if(isTextMatchingCaseSensitive) { - if(sql.startsWith(text)) { - isMatching = true; - break; - } - } else if(sql.length() >= text.length()) { - // Let's avoid creating new String instance. - if(sql.substring(0, text.length()).equalsIgnoreCase(text)) { - isMatching = true; - break; - } - } - } - if(!isMatching) { - return false; - } - break; - } - case EQUALS: { - boolean isMatching = false; - for(String sql: statementInfo.getQueries()) { - if(isTextMatchingCaseSensitive) { - if(sql.equals(text)) { - isMatching = true; - break; - } - } else { - if(sql.equalsIgnoreCase(text)) { - isMatching = true; - break; - } - } - } - if(!isMatching) { - return false; - } - break; - } - case CONTAINS: { - boolean isMatching = false; - for(String sql: statementInfo.getQueries()) { - if(pattern.matcher(sql).matches()) { - isMatching = true; - break; - } - } - if(!isMatching) { - return false; - } - } - case MATCHES_REG_EXP: { - boolean isMatching = false; - for(String sql: statementInfo.getQueries()) { - if(pattern.matcher(sql).matches()) { - isMatching = true; - break; - } - } - if(!isMatching) { - return false; - } - } + hasMatcher = true; + } + if(statementTextMatcher != null) { + if(!statementTextMatcher.matches(statementInfo.getQueries())) { + return false; } + hasMatcher = true; } if(queryTypeSet != null) { if(!queryTypeSet.contains(statementInfo.getQueryType())) { return false; } + hasMatcher = true; } - return true; + return hasMatcher; } + public TextMatcher getThreadNameTextMatcher() { + return threadNameTextMatcher; + } + + public TextMatcher getStatementTextMatcher() { + return statementTextMatcher; + } + + public Set getQueryTypeSet() { + return queryTypeSet; + } + + public boolean isActive() { + return isActive; + } } diff --git a/jOOQ-console/src/main/java/org/jooq/debug/console/LoggerPane.java b/jOOQ-console/src/main/java/org/jooq/debug/console/LoggerPane.java index 5845e1d048..1875cd2289 100644 --- a/jOOQ-console/src/main/java/org/jooq/debug/console/LoggerPane.java +++ b/jOOQ-console/src/main/java/org/jooq/debug/console/LoggerPane.java @@ -101,6 +101,7 @@ import org.jooq.debug.LoggingListener; import org.jooq.debug.QueryLoggingData; import org.jooq.debug.ResultSetLoggingData; import org.jooq.debug.SqlQueryType; +import org.jooq.debug.StatementMatcher; import org.jooq.debug.console.misc.JTableX; import org.jooq.debug.console.misc.RichTextTransferable; import org.jooq.debug.console.misc.Utils; @@ -141,6 +142,7 @@ public class LoggerPane extends JPanel { private JLabel loggerStatusLabel; private JButton loggerOnButton; private JButton loggerOffButton; + private JButton statementMatcherButton; private boolean isLogging; private boolean isReadQueryTypeDisplayed = true; private boolean isWriteQueryTypeDisplayed = true; @@ -180,6 +182,19 @@ public class LoggerPane extends JPanel { } }); loggerHeaderWestPanel.add(loggerOffButton); + statementMatcherButton = new JButton(); + statementMatcherButton.setOpaque(false); + statementMatcherButton.setFocusable(false); + statementMatcherButton.setToolTipText("Filter incoming statements"); + adjustStatementMatcherButton(); + statementMatcherButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + new StatementMatcherDialogBox(LoggerPane.this, LoggerPane.this.debugger).setVisible(true); + adjustStatementMatcherButton(); + } + }); + loggerHeaderWestPanel.add(statementMatcherButton); loggerHeaderPanel.add(loggerHeaderWestPanel, BorderLayout.WEST); JPanel loggerHeaderCenterPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 2, 2)); loggerHeaderCenterPanel.setOpaque(false); @@ -637,6 +652,15 @@ public class LoggerPane extends JPanel { loggerThreadCheckBox.setSelected(false); } + private void adjustStatementMatcherButton() { + StatementMatcher[] loggingStatementMatchers = LoggerPane.this.debugger.getLoggingStatementMatchers(); + if(loggingStatementMatchers != null) { + statementMatcherButton.setIcon(new ImageIcon(getClass().getResource("/org/jooq/debug/console/resources/FilterOn16.png"))); + } else { + statementMatcherButton.setIcon(new ImageIcon(getClass().getResource("/org/jooq/debug/console/resources/FilterOff16.png"))); + } + } + private List queryDebuggingInfoList = new ArrayList(); private List displayedQueryDebuggingInfoList = new ArrayList(); private Map, Integer> queriesToCountMap = new HashMap, Integer>(); diff --git a/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherDialogBox.java b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherDialogBox.java new file mode 100644 index 0000000000..d3656795d2 --- /dev/null +++ b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherDialogBox.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com + * Christopher Deckers, chrriis@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . 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. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.jooq.debug.console; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.jooq.debug.Debugger; +import org.jooq.debug.StatementMatcher; + +@SuppressWarnings("serial") +public class StatementMatcherDialogBox extends JDialog { + + public StatementMatcherDialogBox(Component parent, final Debugger debugger) { + super(SwingUtilities.getWindowAncestor(parent), "Statement filters", ModalityType.DOCUMENT_MODAL); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + Container contentPane = getContentPane(); + final StatementMatchersPane statementMatchersPane = new StatementMatchersPane(debugger.getLoggingStatementMatchers()); + contentPane.add(statementMatchersPane, BorderLayout.CENTER); + JPanel buttonBar = new JPanel(new BorderLayout()); + buttonBar.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + JPanel filterButtonsPane = new JPanel(new GridLayout(1, 2, 2, 0)); + JButton addFilterButton = new JButton("Add filter"); + addFilterButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + statementMatchersPane.addStatementMatcherPane(new StatementMatcherPane(statementMatchersPane, null)); + } + }); + filterButtonsPane.add(addFilterButton); + JButton removeAllFiltersButton = new JButton("Remove all"); + removeAllFiltersButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + statementMatchersPane.removeAllStatementMatcherPanes(); + } + }); + filterButtonsPane.add(removeAllFiltersButton); + buttonBar.add(filterButtonsPane, BorderLayout.WEST); + JPanel rightButtonsPane = new JPanel(new GridLayout(1, 2, 2, 0)); + JButton okButton = new JButton("OK"); + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + StatementMatcher[] statementMatchers = statementMatchersPane.getStatementMatchers(); + debugger.setLoggingStatementMatchers(statementMatchers.length == 0? null: statementMatchers); + dispose(); + } + }); + rightButtonsPane.add(okButton); + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + rightButtonsPane.add(cancelButton); + buttonBar.add(rightButtonsPane, BorderLayout.EAST); + contentPane.add(buttonBar, BorderLayout.SOUTH); + setSize(600, 400); + setLocationRelativeTo(SwingUtilities.getWindowAncestor(parent)); + } + +} diff --git a/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherPane.java b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherPane.java new file mode 100644 index 0000000000..0858846489 --- /dev/null +++ b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatcherPane.java @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com + * Christopher Deckers, chrriis@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . 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. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.jooq.debug.console; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JPanel; +import javax.swing.JToolBar; + +import org.jooq.debug.SqlQueryType; +import org.jooq.debug.StatementMatcher; +import org.jooq.debug.console.misc.TextMatcher; + +@SuppressWarnings("serial") +public class StatementMatcherPane extends JPanel { + + private JCheckBox activeCheckBox; + private JCheckBox threadNameTextMatcherCheckBox; + private TextMatcherPane threadNameTextMatcherPane; + private JCheckBox statementTextMatcherCheckBox; + private TextMatcherPane statementTextMatcherPane; + private JCheckBox statementTypeCheckBox; + private JCheckBox statementTypeSelectCheckBox; + private JCheckBox statementTypeUpdateCheckBox; + private JCheckBox statementTypeInsertCheckBox; + private JCheckBox statementTypeDeleteCheckBox; + private JCheckBox statementTypeOtherCheckBox; + + public StatementMatcherPane(final StatementMatchersPane statementMatchersPane, StatementMatcher statementMatcher) { + super(new GridBagLayout()); + setBorder(BorderFactory.createLineBorder(getBackground().darker())); + if(statementMatcher == null) { + statementMatcher = new StatementMatcher(null, null, null, true); + } + int y = 0; + JPanel northPane = new JPanel(new GridBagLayout()); + activeCheckBox = new JCheckBox("Active", statementMatcher.isActive()); + northPane.add(activeCheckBox, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + JToolBar closeButtonPane = new JToolBar(); + closeButtonPane.setFloatable(false); + JButton closeButton = new JButton(new ImageIcon(getClass().getResource("/org/jooq/debug/console/resources/TabCloseActive14.png"))); + closeButton.setFocusable(false); + closeButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + statementMatchersPane.removeStatementMatcherPane(StatementMatcherPane.this); + } + }); + closeButtonPane.add(closeButton); + northPane.add(closeButtonPane, new GridBagConstraints(1, 0, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0)); + add(northPane, new GridBagConstraints(0, y, 2, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + y++; + TextMatcher statementTextMatcher = statementMatcher.getStatementTextMatcher(); + statementTextMatcherCheckBox = new JCheckBox("Statement", statementTextMatcher != null); + add(statementTextMatcherCheckBox, new GridBagConstraints(0, y, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + statementTextMatcherPane = new TextMatcherPane(statementTextMatcher); + add(statementTextMatcherPane, new GridBagConstraints(1, y, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0)); + y++; + Set queryTypeSet = statementMatcher.getQueryTypeSet(); + statementTypeCheckBox = new JCheckBox("Type", queryTypeSet != null); + add(statementTypeCheckBox, new GridBagConstraints(0, y, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + JPanel typesPane = new JPanel(new GridBagLayout()); + statementTypeSelectCheckBox = new JCheckBox("SELECT", queryTypeSet != null && queryTypeSet.contains(SqlQueryType.SELECT)); + typesPane.add(statementTypeSelectCheckBox, new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + statementTypeUpdateCheckBox = new JCheckBox("UPDATE", queryTypeSet != null && queryTypeSet.contains(SqlQueryType.UPDATE)); + typesPane.add(statementTypeUpdateCheckBox, new GridBagConstraints(1, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0)); + statementTypeInsertCheckBox = new JCheckBox("INSERT", queryTypeSet != null && queryTypeSet.contains(SqlQueryType.INSERT)); + typesPane.add(statementTypeInsertCheckBox, new GridBagConstraints(2, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0)); + statementTypeDeleteCheckBox = new JCheckBox("DELETE", queryTypeSet != null && queryTypeSet.contains(SqlQueryType.DELETE)); + typesPane.add(statementTypeDeleteCheckBox, new GridBagConstraints(3, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0)); + statementTypeOtherCheckBox = new JCheckBox("OTHER", queryTypeSet != null && queryTypeSet.contains(SqlQueryType.OTHER)); + typesPane.add(statementTypeOtherCheckBox, new GridBagConstraints(4, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0)); + add(typesPane, new GridBagConstraints(1, y, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0)); + y++; + TextMatcher threadNameTextMatcher = statementMatcher.getThreadNameTextMatcher(); + threadNameTextMatcherCheckBox = new JCheckBox("Thread name", threadNameTextMatcher != null); + add(threadNameTextMatcherCheckBox, new GridBagConstraints(0, y, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + threadNameTextMatcherPane = new TextMatcherPane(threadNameTextMatcher); + add(threadNameTextMatcherPane, new GridBagConstraints(1, y, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0)); + } + + public StatementMatcher getStatementMatcher() { + boolean isActive = activeCheckBox.isSelected(); + TextMatcher threadNameTextMatcher = threadNameTextMatcherCheckBox.isSelected()? threadNameTextMatcherPane.getTextMatcher(): null; + TextMatcher statementTextMatcher = statementTextMatcherCheckBox.isSelected()? statementTextMatcherPane.getTextMatcher(): null; + Set queryTypeSet; + if(statementTypeCheckBox.isSelected()) { + List typeList = new ArrayList(); + if(statementTypeSelectCheckBox.isSelected()) { + typeList.add(SqlQueryType.SELECT); + } + if(statementTypeUpdateCheckBox.isSelected()) { + typeList.add(SqlQueryType.UPDATE); + } + if(statementTypeInsertCheckBox.isSelected()) { + typeList.add(SqlQueryType.INSERT); + } + if(statementTypeDeleteCheckBox.isSelected()) { + typeList.add(SqlQueryType.DELETE); + } + if(statementTypeOtherCheckBox.isSelected()) { + typeList.add(SqlQueryType.OTHER); + } + queryTypeSet = EnumSet.copyOf(typeList); + } else { + queryTypeSet = null; + } + return new StatementMatcher(threadNameTextMatcher, statementTextMatcher, queryTypeSet, isActive); + } + +} diff --git a/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatchersPane.java b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatchersPane.java new file mode 100644 index 0000000000..b764037aa1 --- /dev/null +++ b/jOOQ-console/src/main/java/org/jooq/debug/console/StatementMatchersPane.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com + * Christopher Deckers, chrriis@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . 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. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.jooq.debug.console; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Rectangle; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.Scrollable; + +import org.jooq.debug.StatementMatcher; + +@SuppressWarnings("serial") +public class StatementMatchersPane extends JPanel { + + private static class ScrollablePane extends JPanel implements Scrollable { + + public ScrollablePane() { + super(new GridLayout(0, 1, 1, 1)); + } + + @Override + public Dimension getPreferredScrollableViewportSize() { + return getPreferredSize(); + } + + @Override + public boolean getScrollableTracksViewportHeight() { + return false; + } + + @Override + public boolean getScrollableTracksViewportWidth() { + return true; + } + + @Override + public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { + return 100; + } + + @Override + public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { + return 10; + } + + } + + private JPanel statementMatcherPanesContainer; + + public StatementMatchersPane(StatementMatcher[] statementMatchers) { + super(new BorderLayout()); + statementMatcherPanesContainer = new ScrollablePane(); + add(new JScrollPane(statementMatcherPanesContainer), BorderLayout.CENTER); + if(statementMatchers != null) { + for(StatementMatcher statementMatcher: statementMatchers) { + addStatementMatcherPane(new StatementMatcherPane(this, statementMatcher)); + } + } + } + + public void addStatementMatcherPane(StatementMatcherPane statementMatcherPane) { + statementMatcherPanesContainer.add(statementMatcherPane); + statementMatcherPanesContainer.revalidate(); + statementMatcherPanesContainer.repaint(); + statementMatcherPanesContainer.scrollRectToVisible(new Rectangle(0, Short.MAX_VALUE, 1, 1)); + } + + void removeAllStatementMatcherPanes() { + statementMatcherPanesContainer.removeAll(); + statementMatcherPanesContainer.revalidate(); + statementMatcherPanesContainer.repaint(); + } + + void removeStatementMatcherPane(StatementMatcherPane statementMatcherPane) { + statementMatcherPanesContainer.remove(statementMatcherPane); + statementMatcherPanesContainer.revalidate(); + statementMatcherPanesContainer.repaint(); + } + + public StatementMatcher[] getStatementMatchers() { + Component[] components = statementMatcherPanesContainer.getComponents(); + StatementMatcher[] statementMatchers = new StatementMatcher[components.length]; + for(int i=0; i= text.length()) { + // Let's avoid creating new String instance. + if(sql.substring(0, text.length()).equalsIgnoreCase(text)) { + return true; + } + } + } + return false; + } + case EQUALS: { + for(String sql: texts) { + if(isCaseSensitive) { + if(sql.equals(text)) { + return true; + } + } else { + if(sql.equalsIgnoreCase(text)) { + return true; + } + } + } + return false; + } + case CONTAINS: { + for(String sql: texts) { + if(pattern.matcher(sql).matches()) { + return true; + } + } + return false; + } + case MATCHES_REG_EXP: { + for(String sql: texts) { + if(pattern.matcher(sql).matches()) { + return true; + } + } + return false; + } + } + return false; + } + + public TextMatchingType getType() { + return type; + } + + public String getText() { + return text; + } + + public boolean isCaseSensitive() { + return isCaseSensitive; + } + +} diff --git a/jOOQ-console/src/main/resources/org/jooq/debug/console/resources/FilterOff16.png b/jOOQ-console/src/main/resources/org/jooq/debug/console/resources/FilterOff16.png new file mode 100644 index 0000000000000000000000000000000000000000..ca5d9a1e1ccc6538af8ebdede9c9ca5de771a7c9 GIT binary patch literal 3678 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 A$^ZZW literal 0 HcmV?d00001 From 297004550e27ff79caa161b7451820099b9d4814 Mon Sep 17 00:00:00 2001 From: Chrriis Date: Tue, 1 May 2012 20:52:43 +0200 Subject: [PATCH 2/2] [#1177] Add SQL Console module to jOOQ - Statement filtering is implemented and exposed in UI. --- .../main/java/org/jooq/debug/console/misc/TextMatcher.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jOOQ-console/src/main/java/org/jooq/debug/console/misc/TextMatcher.java b/jOOQ-console/src/main/java/org/jooq/debug/console/misc/TextMatcher.java index 3ea6c222a9..7d1f473eb4 100644 --- a/jOOQ-console/src/main/java/org/jooq/debug/console/misc/TextMatcher.java +++ b/jOOQ-console/src/main/java/org/jooq/debug/console/misc/TextMatcher.java @@ -71,11 +71,11 @@ public class TextMatcher implements Serializable { switch (type) { case CONTAINS: { String patternText = ".*\\Q" + text.replace("\\E", "\\\\E").replace("\\Q", "\\\\Q") + "\\E.*\\Q"; - pattern = Pattern.compile(patternText, isCaseSensitive? 0: Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + pattern = Pattern.compile(patternText, isCaseSensitive? Pattern.DOTALL: Pattern.DOTALL | Pattern.CASE_INSENSITIVE); break; } case MATCHES_REG_EXP: { - pattern = Pattern.compile(text, isCaseSensitive? 0: Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + pattern = Pattern.compile(text, isCaseSensitive? Pattern.DOTALL: Pattern.DOTALL | Pattern.CASE_INSENSITIVE); break; } }