Merge branch 'master' of git@github.com:jOOQ/jOOQ.git
This commit is contained in:
commit
f8527b3dbb
@ -48,6 +48,7 @@ public class BreakpointHit implements Serializable {
|
||||
STEP_THROUGH,
|
||||
RUN_OVER,
|
||||
RUN,
|
||||
FAIL,
|
||||
}
|
||||
|
||||
private boolean isBeforeExecution;
|
||||
|
||||
@ -47,6 +47,7 @@ import java.util.List;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteType;
|
||||
import org.jooq.debug.BreakpointHit.ExecutionType;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.impl.DefaultExecuteListener;
|
||||
import org.jooq.impl.Factory;
|
||||
|
||||
@ -241,6 +242,9 @@ public class DebugListener extends DefaultExecuteListener {
|
||||
matchingDebugger = null;
|
||||
}
|
||||
switch(executionType) {
|
||||
case FAIL: {
|
||||
throw new DataAccessException("Failing SQL statement.");
|
||||
}
|
||||
case RUN_OVER: {
|
||||
try {
|
||||
ctx.statement().close();
|
||||
|
||||
@ -81,30 +81,32 @@ public class LocalStatementExecutor implements StatementExecutor {
|
||||
boolean isAllowed = true;
|
||||
if(executorContext.isReadOnly()) {
|
||||
String simplifiedSql = sql.replaceAll("'[^']*'", "");
|
||||
Matcher matcher = Pattern.compile("[a-zA-Z_0-9\\$]+").matcher(simplifiedSql);
|
||||
boolean isFirst = true;
|
||||
while(matcher.find()) {
|
||||
String word = simplifiedSql.substring(matcher.start(), matcher.end()).toUpperCase(Locale.ENGLISH);
|
||||
if(isFirst && !word.equals("SELECT")) {
|
||||
switch(SqlQueryType.detectType(simplifiedSql)) {
|
||||
case SELECT:
|
||||
String[] forbiddenWords = new String[] {
|
||||
"INSERT",
|
||||
"UPDATE",
|
||||
"DELETE",
|
||||
"ALTER",
|
||||
"DROP",
|
||||
"CREATE",
|
||||
"EXEC",
|
||||
"EXECUTE",
|
||||
};
|
||||
Matcher matcher = Pattern.compile("[a-zA-Z_0-9\\$]+").matcher(simplifiedSql);
|
||||
while(matcher.find()) {
|
||||
String word = simplifiedSql.substring(matcher.start(), matcher.end()).toUpperCase(Locale.ENGLISH);
|
||||
for(String keyword: forbiddenWords) {
|
||||
if(word.equals(keyword)) {
|
||||
isAllowed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
isAllowed = false;
|
||||
break;
|
||||
}
|
||||
isFirst = false;
|
||||
for(String keyword: new String[] {
|
||||
"INSERT",
|
||||
"UPDATE",
|
||||
"DELETE",
|
||||
"ALTER",
|
||||
"DROP",
|
||||
"CREATE",
|
||||
"EXEC",
|
||||
"EXECUTE",
|
||||
}) {
|
||||
if(word.equals(keyword)) {
|
||||
isAllowed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!isAllowed) {
|
||||
|
||||
@ -52,13 +52,11 @@ import java.util.Set;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
|
||||
import org.jooq.debug.Breakpoint;
|
||||
import org.jooq.debug.SqlQueryType;
|
||||
@ -92,9 +90,7 @@ public class BreakpointEditor extends JPanel {
|
||||
private JPanel processorPane;
|
||||
private JCheckBox beforeExecutionCheckBox;
|
||||
private StatementProcessorPane beforeExecutionProcessorPane;
|
||||
private JRadioButton executeRadioButton;
|
||||
// private JRadioButton doNotExecuteRadioButton;
|
||||
private JRadioButton replaceExecutionRadioButton;
|
||||
private JComboBox executeTypeComboBox;
|
||||
private StatementProcessorPane replacementExecutionProcessorPane;
|
||||
private JCheckBox afterExecutionCheckBox;
|
||||
private StatementProcessorPane afterExecutionProcessorPane;
|
||||
@ -228,35 +224,21 @@ public class BreakpointEditor extends JPanel {
|
||||
beforeExecutionProcessorPane = new StatementProcessorPane(beforeExecutionProcessor);
|
||||
processorPane.add(beforeExecutionProcessorPane, new GridBagConstraints(1, y, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 5, 0, 0), 0, 0));
|
||||
y++;
|
||||
ButtonGroup executionButtonGroup = new ButtonGroup();
|
||||
StatementProcessor replacementExecutionProcessor = breakpoint.getReplacementExecutionProcessor();
|
||||
executeRadioButton = new JRadioButton("Execute");
|
||||
executeRadioButton.setOpaque(false);
|
||||
executionButtonGroup.add(executeRadioButton);
|
||||
processorPane.add(executeRadioButton, new GridBagConstraints(0, y, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
|
||||
y++;
|
||||
executeTypeComboBox = new JComboBox(new String[] {"Execute", "Replace with"});
|
||||
// doNotExecuteRadioButton = new JRadioButton("Do not execute");
|
||||
// executionButtonGroup.add(doNotExecuteRadioButton);
|
||||
// processorPane.add(doNotExecuteRadioButton, new GridBagConstraints(0, y, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
|
||||
// y++;
|
||||
replaceExecutionRadioButton = new JRadioButton("Replace with: ");
|
||||
replaceExecutionRadioButton.setOpaque(false);
|
||||
executionButtonGroup.add(replaceExecutionRadioButton);
|
||||
if(replacementExecutionProcessor != null) {
|
||||
replaceExecutionRadioButton.setSelected(true);
|
||||
executeTypeComboBox.setSelectedIndex(1);
|
||||
} else {
|
||||
executeRadioButton.setSelected(true);
|
||||
executeTypeComboBox.setSelectedIndex(0);
|
||||
}
|
||||
processorPane.add(replaceExecutionRadioButton, new GridBagConstraints(0, y, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
|
||||
processorPane.add(executeTypeComboBox, new GridBagConstraints(0, y, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
|
||||
replacementExecutionProcessorPane = new StatementProcessorPane(breakpoint.getReplacementExecutionProcessor());
|
||||
processorPane.add(replacementExecutionProcessorPane, new GridBagConstraints(1, y, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 0), 0, 0));
|
||||
executeRadioButton.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
adjustStates();
|
||||
}
|
||||
});
|
||||
replaceExecutionRadioButton.addItemListener(new ItemListener() {
|
||||
executeTypeComboBox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
adjustStates();
|
||||
@ -296,10 +278,9 @@ public class BreakpointEditor extends JPanel {
|
||||
processorPane.setVisible(isActive && breakpointTypeComboBox.getSelectedItem() == PROCESS);
|
||||
beforeExecutionCheckBox.setEnabled(isActive);
|
||||
beforeExecutionProcessorPane.setLocked(!isActive || !beforeExecutionCheckBox.isSelected());
|
||||
executeRadioButton.setEnabled(isActive);
|
||||
replaceExecutionRadioButton.setEnabled(isActive);
|
||||
executeTypeComboBox.setEnabled(isActive);
|
||||
// doNotExecuteRadioButton;
|
||||
replacementExecutionProcessorPane.setLocked(!isActive || !replaceExecutionRadioButton.isSelected());
|
||||
replacementExecutionProcessorPane.setLocked(!isActive || executeTypeComboBox.getSelectedIndex() != 1);
|
||||
afterExecutionCheckBox.setEnabled(isActive);
|
||||
afterExecutionProcessorPane.setLocked(!isActive || !afterExecutionCheckBox.isSelected());
|
||||
}
|
||||
@ -345,7 +326,7 @@ public class BreakpointEditor extends JPanel {
|
||||
StatementProcessor afterExecutionProcessor = null;
|
||||
if(!isBreaking) {
|
||||
beforeExecutionProcessor = beforeExecutionCheckBox.isSelected()? beforeExecutionProcessorPane.getStatementProcessor(): null;
|
||||
replacementExecutionProcessor = replaceExecutionRadioButton.isSelected()? replacementExecutionProcessorPane.getStatementProcessor(): null;
|
||||
replacementExecutionProcessor = executeTypeComboBox.getSelectedIndex() == 1? replacementExecutionProcessorPane.getStatementProcessor(): null;
|
||||
afterExecutionProcessor = afterExecutionCheckBox.isSelected()? afterExecutionProcessorPane.getStatementProcessor(): null;
|
||||
}
|
||||
return new Breakpoint(id, hitCount, statementMatcher, isBreaking, beforeExecutionProcessor, replacementExecutionProcessor, afterExecutionProcessor);
|
||||
|
||||
@ -120,10 +120,18 @@ public class BreakpointHitEditor extends JPanel {
|
||||
executeTypeNoneRadioButton.setSelected(true);
|
||||
executionTypeGroup.add(executeTypeNoneRadioButton);
|
||||
executionTypePane.add(executeTypeNoneRadioButton);
|
||||
JRadioButton executeTypeBreakRadioButton = new JRadioButton("Execute and break");
|
||||
final JRadioButton executeTypeBreakRadioButton = new JRadioButton("Execute and break");
|
||||
executeTypeBreakRadioButton.setOpaque(false);
|
||||
executionTypeGroup.add(executeTypeBreakRadioButton);
|
||||
executionTypePane.add(executeTypeBreakRadioButton);
|
||||
final JRadioButton executeTypeSkipRadioButton = new JRadioButton("Skip");
|
||||
executeTypeSkipRadioButton.setOpaque(false);
|
||||
executionTypeGroup.add(executeTypeSkipRadioButton);
|
||||
executionTypePane.add(executeTypeSkipRadioButton);
|
||||
final JRadioButton executeTypeFailRadioButton = new JRadioButton("Throw exception");
|
||||
executeTypeFailRadioButton.setOpaque(false);
|
||||
executionTypeGroup.add(executeTypeFailRadioButton);
|
||||
executionTypePane.add(executeTypeFailRadioButton);
|
||||
breakpointHitExecutionPane.add(executionTypePane, new GridBagConstraints(0, y++, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 0, 0, 0), 0, 0));
|
||||
JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
|
||||
buttonPane.setOpaque(false);
|
||||
@ -134,7 +142,20 @@ public class BreakpointHitEditor extends JPanel {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if(breakpointHit.isBeforeExecution()) {
|
||||
breakpointHit.setExecutionType(executeTypeNoneRadioButton.isSelected()? ExecutionType.RUN: ExecutionType.STEP_THROUGH, replaceStatementCheckBox.isSelected()? replacementSQLTextArea.getText(): null);
|
||||
String replacementSQL = null;
|
||||
ExecutionType executionType = ExecutionType.RUN;
|
||||
if(executeTypeNoneRadioButton.isSelected()) {
|
||||
executionType = ExecutionType.RUN;
|
||||
replacementSQL = replaceStatementCheckBox.isSelected()? replacementSQLTextArea.getText(): null;
|
||||
} else if(executeTypeBreakRadioButton.isSelected()) {
|
||||
executionType = ExecutionType.STEP_THROUGH;
|
||||
replacementSQL = replaceStatementCheckBox.isSelected()? replacementSQLTextArea.getText(): null;
|
||||
} else if(executeTypeSkipRadioButton.isSelected()) {
|
||||
executionType = ExecutionType.RUN_OVER;
|
||||
} else if(executeTypeFailRadioButton.isSelected()) {
|
||||
executionType = ExecutionType.FAIL;
|
||||
}
|
||||
breakpointHit.setExecutionType(executionType, replacementSQL);
|
||||
} else {
|
||||
breakpointHit.setExecutionType(ExecutionType.RUN, null);
|
||||
}
|
||||
|
||||
@ -66,13 +66,16 @@ import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import org.jooq.debug.Debugger;
|
||||
import org.jooq.debug.DebuggerRegistry;
|
||||
import org.jooq.debug.LocalDebugger;
|
||||
import org.jooq.debug.console.misc.JSedRegExBuilder;
|
||||
import org.jooq.debug.console.remote.ClientDebugger;
|
||||
|
||||
/**
|
||||
@ -115,6 +118,21 @@ public class Console extends JFrame {
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
JMenu fileMenu = new JMenu("File");
|
||||
fileMenu.setMnemonic('F');
|
||||
JMenuItem regExpEditorMenuItem = new JMenuItem("Reg. Exp. Editor");
|
||||
regExpEditorMenuItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JDialog dialog = new JDialog(Console.this, "Reg. Exp Editor");
|
||||
JPanel contentPane = new JPanel(new BorderLayout());
|
||||
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||
contentPane.add(new JSedRegExBuilder("/foo/bar/gi", "axFooax\nbxfoobx"), BorderLayout.CENTER);
|
||||
dialog.add(contentPane, BorderLayout.CENTER);
|
||||
dialog.setSize(600, 400);
|
||||
dialog.setVisible(true);
|
||||
dialog.setLocationRelativeTo(Console.this);
|
||||
}
|
||||
});
|
||||
fileMenu.add(regExpEditorMenuItem);
|
||||
JMenuItem exitMenuItem = new JMenuItem("Exit");
|
||||
exitMenuItem.setMnemonic('x');
|
||||
exitMenuItem.addActionListener(new ActionListener() {
|
||||
@ -153,15 +171,17 @@ public class Console extends JFrame {
|
||||
final JDialog aboutDialog = new JDialog(Console.this, "About jOOQ Console", ModalityType.APPLICATION_MODAL);
|
||||
aboutDialog.setResizable(false);
|
||||
Container contentPane = aboutDialog.getContentPane();
|
||||
JPanel centerPane = new JPanel(new GridBagLayout());
|
||||
centerPane.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
centerPane.add(new JLabel("jOOQ library: "), new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
centerPane.add(new JLabel("Lukas Eder"), new GridBagConstraints(1, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
centerPane.add(new JLabel("jOOQ Console: "), new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
centerPane.add(new JLabel("Christopher Deckers"), new GridBagConstraints(1, 1, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
centerPane.add(new JLabel("License: "), new GridBagConstraints(0, 2, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
centerPane.add(new JLabel("Apache License, Version 2.0"), new GridBagConstraints(1, 2, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
centerPane.add(new JLabel("Web site: "), new GridBagConstraints(0, 3, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
JTabbedPane tabbedPane = new JTabbedPane();
|
||||
JPanel aboutPane = new JPanel(new GridBagLayout());
|
||||
aboutPane.setOpaque(false);
|
||||
aboutPane.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
aboutPane.add(new JLabel("jOOQ library: "), new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
aboutPane.add(new JLabel("Lukas Eder"), new GridBagConstraints(1, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
aboutPane.add(new JLabel("jOOQ Console: "), new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
aboutPane.add(new JLabel("Christopher Deckers"), new GridBagConstraints(1, 1, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
aboutPane.add(new JLabel("License: "), new GridBagConstraints(0, 2, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
aboutPane.add(new JLabel("Apache License, Version 2.0"), new GridBagConstraints(1, 2, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
aboutPane.add(new JLabel("Web site: "), new GridBagConstraints(0, 3, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
JLabel siteLabel = new JLabel("http://www.jooq.org");
|
||||
siteLabel.setForeground(Color.BLUE);
|
||||
Map<TextAttribute, Object> attributeMap = new HashMap<TextAttribute, Object>();
|
||||
@ -179,8 +199,30 @@ public class Console extends JFrame {
|
||||
}
|
||||
}
|
||||
});
|
||||
centerPane.add(siteLabel, new GridBagConstraints(1, 3, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
contentPane.add(centerPane, BorderLayout.CENTER);
|
||||
aboutPane.add(siteLabel, new GridBagConstraints(1, 3, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
tabbedPane.addTab("About", aboutPane);
|
||||
JPanel disclaimerPane = new JPanel(new BorderLayout());
|
||||
disclaimerPane.setBorder(BorderFactory.createEmptyBorder(2, 5, 5, 5));
|
||||
disclaimerPane.setOpaque(false);
|
||||
JTextArea textArea = new JTextArea(
|
||||
"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."
|
||||
);
|
||||
textArea.setLineWrap(true);
|
||||
textArea.setWrapStyleWord(true);
|
||||
textArea.setEditable(false);
|
||||
disclaimerPane.add(new JScrollPane(textArea));
|
||||
tabbedPane.addTab("Disclaimer", disclaimerPane);
|
||||
contentPane.add(tabbedPane, BorderLayout.CENTER);
|
||||
JPanel southPane = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||
JButton okButton = new JButton("OK");
|
||||
okButton.addActionListener(new ActionListener() {
|
||||
@ -191,7 +233,7 @@ public class Console extends JFrame {
|
||||
});
|
||||
southPane.add(okButton);
|
||||
contentPane.add(southPane, BorderLayout.SOUTH);
|
||||
aboutDialog.pack();
|
||||
aboutDialog.setSize(500, 400);
|
||||
aboutDialog.setLocationRelativeTo(Console.this);
|
||||
aboutDialog.setVisible(true);
|
||||
}
|
||||
|
||||
@ -86,6 +86,7 @@ import org.jooq.debug.console.misc.CheckBoxNode;
|
||||
import org.jooq.debug.console.misc.CheckBoxNodeEditor;
|
||||
import org.jooq.debug.console.misc.CheckBoxNodeRenderer;
|
||||
import org.jooq.debug.console.misc.InvisibleSplitPane;
|
||||
import org.jooq.debug.console.misc.TreeDataTip;
|
||||
|
||||
/**
|
||||
* @author Christopher Deckers
|
||||
@ -111,16 +112,18 @@ public class DebuggerPane extends JPanel {
|
||||
setOpaque(false);
|
||||
this.debugger = debugger;
|
||||
JPanel westPane = new JPanel(new BorderLayout());
|
||||
westPane.setBorder(BorderFactory.createTitledBorder("Breakpoints"));
|
||||
westPane.setOpaque(false);
|
||||
JPanel breakpointAddPane = new JPanel(new GridBagLayout());
|
||||
breakpointAddPane.setOpaque(false);
|
||||
breakpointAddPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 2, 0));
|
||||
breakpointAddPane.add(new JLabel("Name "), new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
final JTextField addBreakpointTextField = new JTextField(7);
|
||||
breakpointAddPane.add(addBreakpointTextField, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
breakpointAddPane.add(addBreakpointTextField, new GridBagConstraints(1, 0, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 2, 0, 0), 0, 0));
|
||||
final JButton addBreakpointButton = new JButton("Add");
|
||||
addBreakpointButton.setOpaque(false);
|
||||
addBreakpointButton.setEnabled(false);
|
||||
breakpointAddPane.add(addBreakpointButton, new GridBagConstraints(1, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 2, 0, 0), 0, 0));
|
||||
breakpointAddPane.add(addBreakpointButton, new GridBagConstraints(2, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 2, 0, 0), 0, 0));
|
||||
addBreakpointTextField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
@ -205,6 +208,7 @@ public class DebuggerPane extends JPanel {
|
||||
breakpointTree.setCellEditor(new CheckBoxNodeEditor(breakpointTree));
|
||||
breakpointTree.setCellRenderer(new CheckBoxNodeRenderer(breakpointTree));
|
||||
breakpointTree.setEditable(true);
|
||||
TreeDataTip.activate(breakpointTree);
|
||||
JScrollPane breakpointTreeScrollPane = new JScrollPane(breakpointTree);
|
||||
breakpointTreeScrollPane.setPreferredSize(new Dimension(200, 200));
|
||||
westPane.add(breakpointTreeScrollPane, BorderLayout.CENTER);
|
||||
@ -509,9 +513,19 @@ public class DebuggerPane extends JPanel {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode)paths[0].getLastPathComponent();
|
||||
if(node instanceof CheckBoxNode) {
|
||||
Object o = node.getUserObject();
|
||||
eastPane.add(new BreakpointEditor(this, (Breakpoint)o));
|
||||
JPanel contentPane = new JPanel(new BorderLayout());
|
||||
contentPane.setBorder(BorderFactory.createTitledBorder("Breakpoint configuration"));
|
||||
contentPane.setOpaque(false);
|
||||
BreakpointEditor c = new BreakpointEditor(this, (Breakpoint)o);
|
||||
contentPane.add(c);
|
||||
eastPane.add(contentPane);
|
||||
} else if(node instanceof BreakpointHitNode) {
|
||||
eastPane.add(new BreakpointHitEditor(debugger, this, (BreakpointHitNode)node));
|
||||
JPanel contentPane = new JPanel(new BorderLayout());
|
||||
contentPane.setBorder(BorderFactory.createTitledBorder("Breakpoint hit details"));
|
||||
contentPane.setOpaque(false);
|
||||
BreakpointHitEditor c = new BreakpointHitEditor(debugger, this, (BreakpointHitNode)node);
|
||||
contentPane.add(c);
|
||||
eastPane.add(contentPane);
|
||||
}
|
||||
}
|
||||
eastPane.revalidate();
|
||||
|
||||
@ -0,0 +1,206 @@
|
||||
/**
|
||||
* 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.misc;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import javax.swing.CellRendererPane;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JToolTip;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.Popup;
|
||||
import javax.swing.PopupFactory;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.MouseInputAdapter;
|
||||
import javax.swing.event.MouseInputListener;
|
||||
import javax.swing.tree.TreeCellRenderer;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
public class TreeDataTip {
|
||||
|
||||
private TreeDataTip() {}
|
||||
|
||||
public static void activate(final JTree tree) {
|
||||
MouseInputListener dataTipListener = new MouseInputAdapter() {
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
showTip(e.getPoint());
|
||||
}
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
showTip(e.getPoint());
|
||||
}
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
hideTip();
|
||||
}
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
hideTip();
|
||||
}
|
||||
private Popup popup;
|
||||
private int currentRow = -1;
|
||||
private void hideTip() {
|
||||
if(popup != null) {
|
||||
popup.hide();
|
||||
popup = null;
|
||||
}
|
||||
}
|
||||
private void showTip(Point mousePosition) {
|
||||
int row = tree.getRowForLocation(mousePosition.x, mousePosition.y);
|
||||
if(row != currentRow) {
|
||||
hideTip();
|
||||
currentRow = row;
|
||||
if(row >= 0) {
|
||||
TreePath treePath = tree.getPathForRow(row);
|
||||
TreeCellRenderer renderer = tree.getCellRenderer();
|
||||
boolean isSelected = false;//breakpointTree.isPathSelected(treePath);
|
||||
boolean isExpanded = tree.isExpanded(treePath);
|
||||
boolean hasFocus = false;//tree.hasFocus() && rowIndex == tree.getLeadSelectionRow();
|
||||
Object item = treePath.getLastPathComponent();
|
||||
boolean isLeaf = tree.getModel().isLeaf(item);
|
||||
final JComponent rendererComponent = (JComponent)renderer.getTreeCellRendererComponent(tree, item, isSelected, isExpanded, isLeaf, row, hasFocus);
|
||||
rendererComponent.setFont(tree.getFont());
|
||||
Rectangle visRect = tree.getVisibleRect();
|
||||
Rectangle cellBounds = tree.getPathBounds(treePath);
|
||||
Rectangle visibleCellRectangle = cellBounds.intersection(visRect);
|
||||
if (!visibleCellRectangle.contains(mousePosition)) {
|
||||
return;
|
||||
}
|
||||
Dimension rendCompDim = rendererComponent.getMinimumSize();
|
||||
Rectangle rendCompBounds = new Rectangle(cellBounds.getLocation(), rendCompDim);
|
||||
visRect.x -= 1000;
|
||||
visRect.width += 1000;
|
||||
visRect.y -= 1000;
|
||||
visRect.height += 2000;
|
||||
// We do not care about vertical visibility.
|
||||
rendCompBounds.height = 1;
|
||||
if(cellBounds.contains(rendCompBounds) && visRect.contains(rendCompBounds)) {
|
||||
return;
|
||||
}
|
||||
Dimension preferredSize = rendererComponent.getPreferredSize();
|
||||
Point tipPosition = cellBounds.getLocation();
|
||||
int width = Math.max(cellBounds.width, preferredSize.width);
|
||||
int height = cellBounds.height;//Math.max(cellBounds.height, preferredSize.height); // We don't care about vertical visibility
|
||||
Dimension tipDimension = new Dimension(width, height);
|
||||
final Color backgroundColor = tree.getBackground();
|
||||
class DataTipComponent extends JToolTip {
|
||||
private CellRendererPane rendererPane = new CellRendererPane();
|
||||
private boolean isHeavyWeight;
|
||||
public DataTipComponent() {
|
||||
add(rendererPane);
|
||||
setFocusable(false);
|
||||
setBorder(null);
|
||||
enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_WHEEL_EVENT_MASK);
|
||||
}
|
||||
@Override
|
||||
public void updateUI() {
|
||||
}
|
||||
@Override
|
||||
public boolean contains(int x, int y) {
|
||||
return isHeavyWeight;
|
||||
}
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
// Leave the component's opacity settings as is, just paint the background myself.
|
||||
// This seems to be the only viable solution: DefaultTableCellRenderer overrides isOpaque() and returns
|
||||
// true only if renderer color does not equal parent color. The problem is that rendererPane.paintComponent()
|
||||
// re-parents the renderer.
|
||||
g.setColor(backgroundColor);
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
g.fillRect(0, 0, width, height);
|
||||
g.setColor(Color.black);
|
||||
g.drawRect(0, 0, width - 1, height - 1);
|
||||
g.setClip(1, 1, width - 2, height - 2);
|
||||
int row = currentRow;
|
||||
TreePath treePath = tree.getPathForRow(row);
|
||||
boolean isSelected = false;//breakpointTree.isPathSelected(treePath);
|
||||
boolean isExpanded = tree.isExpanded(treePath);
|
||||
boolean hasFocus = false;//tree.hasFocus() && rowIndex == tree.getLeadSelectionRow();
|
||||
Object item = treePath.getLastPathComponent();
|
||||
boolean isLeaf = tree.getModel().isLeaf(item);
|
||||
TreeCellRenderer renderer = tree.getCellRenderer();
|
||||
JComponent rendererComponent = (JComponent)renderer.getTreeCellRendererComponent(tree, item, isSelected, isExpanded, isLeaf, row, hasFocus);
|
||||
rendererComponent.setFont(tree.getFont());
|
||||
rendererPane.paintComponent(g, rendererComponent, this, 1, 1, width - 1, height - 1);
|
||||
}
|
||||
public void setHeavyWeight(boolean isHeavyWeight) {
|
||||
this.isHeavyWeight = isHeavyWeight;
|
||||
}
|
||||
}
|
||||
DataTipComponent dataTipComponent = new DataTipComponent();
|
||||
Dimension tipDimensionClipped = new Dimension(tipDimension.width, tipDimension.height);
|
||||
Window windowAncestor = SwingUtilities.getWindowAncestor(tree);
|
||||
GraphicsConfiguration gc = windowAncestor.getGraphicsConfiguration();
|
||||
Rectangle screenBounds = gc.getBounds();
|
||||
// Chrriis: we add the border around, not in
|
||||
Point tipScreenPosition = new Point(tipPosition.x, tipPosition.y);
|
||||
SwingUtilities.convertPointToScreen(tipScreenPosition, tree);
|
||||
Point tipPositionClipped = new Point();
|
||||
tipPositionClipped.x = Math.max(tipScreenPosition.x - 1, screenBounds.x);
|
||||
tipPositionClipped.y = Math.max(tipScreenPosition.y - 1, screenBounds.y);
|
||||
// Chrriis: we add the border around, not in
|
||||
tipDimensionClipped.width = Math.min(screenBounds.x + screenBounds.width - tipPositionClipped.x, tipDimensionClipped.width + 2);
|
||||
tipDimensionClipped.height = Math.min(screenBounds.y + screenBounds.height - tipPositionClipped.y, tipDimensionClipped.height + 2);
|
||||
SwingUtilities.convertPointFromScreen(tipPositionClipped, tree);
|
||||
dataTipComponent.setPreferredSize(tipDimensionClipped);
|
||||
SwingUtilities.convertPointToScreen(tipPosition, tree);
|
||||
PopupFactory popupFactory = PopupFactory.getSharedInstance();
|
||||
popup = popupFactory.getPopup(tree, dataTipComponent, tipPosition.x - 1, tipPosition.y - 1);
|
||||
popup.show();
|
||||
Window componentWindow = SwingUtilities.windowForComponent(tree);
|
||||
Window tipWindow = SwingUtilities.windowForComponent(dataTipComponent);
|
||||
boolean isHeavyWeight = tipWindow != null && tipWindow != componentWindow;
|
||||
dataTipComponent.setHeavyWeight(isHeavyWeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
tree.addMouseListener(dataTipListener);
|
||||
tree.addMouseMotionListener(dataTipListener);
|
||||
}
|
||||
|
||||
}
|
||||
@ -59,7 +59,21 @@ public class ClientStatementExecutionResultSetResult implements StatementExecuti
|
||||
columnNames = rsResult.getColumnNames();
|
||||
typeInfos = rsResult.getTypeInfos();
|
||||
columnClasses = rsResult.getColumnClasses();
|
||||
rowData = rsResult.getRowData();
|
||||
Object[][] rowData_ = rsResult.getRowData();
|
||||
rowData = new Object[rowData_.length][];
|
||||
for(int i=0; i<rowData_.length; i++) {
|
||||
Object[] columnData_ = rowData_[i];
|
||||
Object[] columnData = new Object[columnData_.length];
|
||||
for(int j=0; j<columnData_.length; j++) {
|
||||
Object o = columnData_[j];
|
||||
if(o != null && !(o instanceof Serializable)) {
|
||||
// Best effort conversion because we are in remote mode...
|
||||
o = String.valueOf(o);
|
||||
}
|
||||
columnData[j] = o;
|
||||
}
|
||||
rowData[i] = columnData;
|
||||
}
|
||||
rowCount = rsResult.getRowCount();
|
||||
resultSetParsingDuration = rsResult.getResultSetParsingDuration();
|
||||
retainParsedRSDataRowCountThreshold = rsResult.getRetainParsedRSDataRowCountThreshold();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user