org.h2.tools.GUIConsole Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of h2-mvstore Show documentation
Show all versions of h2-mvstore Show documentation
Fork of h2database to maintain Java 8 compatibility
The newest version!
/*
* Copyright 2004-2023 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (https://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.tools;
import java.awt.Button;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Label;
import java.awt.MenuItem;
import java.awt.Panel;
import java.awt.PopupMenu;
import java.awt.SystemColor;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.util.Locale;
import org.h2.jdbc.JdbcConnection;
import org.h2.util.Utils;
/**
* Console for environments with AWT support.
*/
public class GUIConsole extends Console implements ActionListener, MouseListener, WindowListener {
private long lastOpenNs;
private boolean trayIconUsed;
private Font font;
private Frame statusFrame;
private TextField urlText;
private Button startBrowser;
private Frame createFrame;
private TextField pathField, userField, passwordField, passwordConfirmationField;
private Button createButton;
private TextArea errorArea;
private Object tray;
private Object trayIcon;
@Override
void show() {
if (!GraphicsEnvironment.isHeadless()) {
loadFont();
try {
if (!createTrayIcon()) {
showStatusWindow();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static Image loadImage(String name) {
try {
byte[] imageData = Utils.getResource(name);
if (imageData == null) {
return null;
}
return Toolkit.getDefaultToolkit().createImage(imageData);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
@Override
public void shutdown() {
super.shutdown();
if (statusFrame != null) {
statusFrame.dispose();
statusFrame = null;
}
if (trayIconUsed) {
try {
// tray.remove(trayIcon);
Utils.callMethod(tray, "remove", trayIcon);
} catch (Exception e) {
// ignore
} finally {
trayIcon = null;
tray = null;
trayIconUsed = false;
}
System.gc();
// Mac OS X: Console tool process did not stop on exit
String os = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
if (os.contains("mac")) {
for (Thread t : Thread.getAllStackTraces().keySet()) {
if (t.getName().startsWith("AWT-")) {
t.interrupt();
}
}
}
Thread.currentThread().interrupt();
// throw new ThreadDeath();
}
}
private void loadFont() {
if (isWindows) {
font = new Font("Dialog", Font.PLAIN, 11);
} else {
font = new Font("Dialog", Font.PLAIN, 12);
}
}
private boolean createTrayIcon() {
try {
// SystemTray.isSupported();
boolean supported = (Boolean) Utils.callStaticMethod(
"java.awt.SystemTray.isSupported");
if (!supported) {
return false;
}
PopupMenu menuConsole = new PopupMenu();
MenuItem itemConsole = new MenuItem("H2 Console");
itemConsole.setActionCommand("console");
itemConsole.addActionListener(this);
itemConsole.setFont(font);
menuConsole.add(itemConsole);
MenuItem itemCreate = new MenuItem("Create a new database...");
itemCreate.setActionCommand("showCreate");
itemCreate.addActionListener(this);
itemCreate.setFont(font);
menuConsole.add(itemCreate);
MenuItem itemStatus = new MenuItem("Status");
itemStatus.setActionCommand("status");
itemStatus.addActionListener(this);
itemStatus.setFont(font);
menuConsole.add(itemStatus);
MenuItem itemExit = new MenuItem("Exit");
itemExit.setFont(font);
itemExit.setActionCommand("exit");
itemExit.addActionListener(this);
menuConsole.add(itemExit);
// tray = SystemTray.getSystemTray();
tray = Utils.callStaticMethod("java.awt.SystemTray.getSystemTray");
// Dimension d = tray.getTrayIconSize();
Dimension d = (Dimension) Utils.callMethod(tray, "getTrayIconSize");
String iconFile;
if (d.width >= 24 && d.height >= 24) {
iconFile = "/org/h2/res/h2-24.png";
} else if (d.width >= 22 && d.height >= 22) {
// for Mac OS X 10.8.1 with retina display:
// the reported resolution is 22 x 22, but the image
// is scaled and the real resolution is 44 x 44
iconFile = "/org/h2/res/h2-64-t.png";
// iconFile = "/org/h2/res/h2-22-t.png";
} else {
iconFile = "/org/h2/res/h2.png";
}
Image icon = loadImage(iconFile);
// trayIcon = new TrayIcon(image, "H2 Database Engine",
// menuConsole);
trayIcon = Utils.newInstance("java.awt.TrayIcon",
icon, "H2 Database Engine", menuConsole);
// trayIcon.addMouseListener(this);
Utils.callMethod(trayIcon, "addMouseListener", this);
// tray.add(trayIcon);
Utils.callMethod(tray, "add", trayIcon);
this.trayIconUsed = true;
return true;
} catch (Exception e) {
return false;
}
}
private void showStatusWindow() {
if (statusFrame != null) {
return;
}
statusFrame = new Frame("H2 Console");
statusFrame.addWindowListener(this);
Image image = loadImage("/org/h2/res/h2.png");
if (image != null) {
statusFrame.setIconImage(image);
}
statusFrame.setResizable(false);
statusFrame.setBackground(SystemColor.control);
GridBagLayout layout = new GridBagLayout();
statusFrame.setLayout(layout);
// the main panel keeps everything together
Panel mainPanel = new Panel(layout);
GridBagConstraints constraintsPanel = new GridBagConstraints();
constraintsPanel.gridx = 0;
constraintsPanel.weightx = 1.0D;
constraintsPanel.weighty = 1.0D;
constraintsPanel.fill = GridBagConstraints.BOTH;
constraintsPanel.insets = new Insets(0, 10, 0, 10);
constraintsPanel.gridy = 0;
GridBagConstraints constraintsButton = new GridBagConstraints();
constraintsButton.gridx = 0;
constraintsButton.gridwidth = 2;
constraintsButton.insets = new Insets(10, 0, 0, 0);
constraintsButton.gridy = 1;
constraintsButton.anchor = GridBagConstraints.EAST;
GridBagConstraints constraintsTextField = new GridBagConstraints();
constraintsTextField.fill = GridBagConstraints.HORIZONTAL;
constraintsTextField.gridy = 0;
constraintsTextField.weightx = 1.0;
constraintsTextField.insets = new Insets(0, 5, 0, 0);
constraintsTextField.gridx = 1;
GridBagConstraints constraintsLabel = new GridBagConstraints();
constraintsLabel.gridx = 0;
constraintsLabel.gridy = 0;
Label label = new Label("H2 Console URL:", Label.LEFT);
label.setFont(font);
mainPanel.add(label, constraintsLabel);
urlText = new TextField();
urlText.setEditable(false);
urlText.setFont(font);
urlText.setText(web.getURL());
if (isWindows) {
urlText.setFocusable(false);
}
mainPanel.add(urlText, constraintsTextField);
startBrowser = new Button("Start Browser");
startBrowser.setFocusable(false);
startBrowser.setActionCommand("console");
startBrowser.addActionListener(this);
startBrowser.setFont(font);
mainPanel.add(startBrowser, constraintsButton);
statusFrame.add(mainPanel, constraintsPanel);
int width = 300, height = 120;
statusFrame.setSize(width, height);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
statusFrame.setLocation((screenSize.width - width) / 2,
(screenSize.height - height) / 2);
try {
statusFrame.setVisible(true);
} catch (Throwable t) {
// ignore
// some systems don't support this method, for example IKVM
// however it still works
}
try {
// ensure this window is in front of the browser
statusFrame.setAlwaysOnTop(true);
statusFrame.setAlwaysOnTop(false);
} catch (Throwable t) {
// ignore
}
}
private void startBrowser() {
if (web != null) {
String url = web.getURL();
if (urlText != null) {
urlText.setText(url);
}
long now = Utils.currentNanoTime();
if (lastOpenNs == 0 || now - lastOpenNs > 100_000_000L) {
lastOpenNs = now;
openBrowser(url);
}
}
}
private void showCreateDatabase() {
if (createFrame != null) {
return;
}
createFrame = new Frame("H2 Console");
createFrame.addWindowListener(this);
Image image = loadImage("/org/h2/res/h2.png");
if (image != null) {
createFrame.setIconImage(image);
}
createFrame.setResizable(false);
createFrame.setBackground(SystemColor.control);
GridBagLayout layout = new GridBagLayout();
createFrame.setLayout(layout);
// the main panel keeps everything together
Panel mainPanel = new Panel(layout);
GridBagConstraints constraints;
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.insets = new Insets(10, 0, 0, 0);
constraints.gridx = 0;
constraints.gridy = 0;
Label urlLabel = new Label("Database path:", Label.LEFT);
urlLabel.setFont(font);
mainPanel.add(urlLabel, constraints);
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridy = 0;
constraints.weightx = 1d;
constraints.insets = new Insets(10, 5, 0, 0);
constraints.gridx = 1;
pathField = new TextField();
pathField.setFont(font);
pathField.setText("./test");
mainPanel.add(pathField, constraints);
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridx = 0;
constraints.gridy = 1;
Label userLabel = new Label("Username:", Label.LEFT);
userLabel.setFont(font);
mainPanel.add(userLabel, constraints);
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridy = 1;
constraints.weightx = 1d;
constraints.insets = new Insets(0, 5, 0, 0);
constraints.gridx = 1;
userField = new TextField();
userField.setFont(font);
userField.setText("sa");
mainPanel.add(userField, constraints);
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridx = 0;
constraints.gridy = 2;
Label passwordLabel = new Label("Password:", Label.LEFT);
passwordLabel.setFont(font);
mainPanel.add(passwordLabel, constraints);
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridy = 2;
constraints.weightx = 1d;
constraints.insets = new Insets(0, 5, 0, 0);
constraints.gridx = 1;
passwordField = new TextField();
passwordField.setFont(font);
passwordField.setEchoChar('*');
mainPanel.add(passwordField, constraints);
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridx = 0;
constraints.gridy = 3;
Label passwordConfirmationLabel = new Label("Password confirmation:", Label.LEFT);
passwordConfirmationLabel.setFont(font);
mainPanel.add(passwordConfirmationLabel, constraints);
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridy = 3;
constraints.weightx = 1d;
constraints.insets = new Insets(0, 5, 0, 0);
constraints.gridx = 1;
passwordConfirmationField = new TextField();
passwordConfirmationField.setFont(font);
passwordConfirmationField.setEchoChar('*');
mainPanel.add(passwordConfirmationField, constraints);
constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridwidth = 2;
constraints.insets = new Insets(10, 0, 0, 0);
constraints.gridy = 4;
constraints.anchor = GridBagConstraints.EAST;
createButton = new Button("Create");
createButton.setFocusable(false);
createButton.setActionCommand("create");
createButton.addActionListener(this);
createButton.setFont(font);
mainPanel.add(createButton, constraints);
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridy = 5;
constraints.weightx = 1d;
constraints.insets = new Insets(10, 0, 0, 0);
constraints.gridx = 0;
constraints.gridwidth = 2;
errorArea = new TextArea();
errorArea.setFont(font);
errorArea.setEditable(false);
mainPanel.add(errorArea, constraints);
constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.weightx = 1d;
constraints.weighty = 1d;
constraints.fill = GridBagConstraints.BOTH;
constraints.insets = new Insets(0, 10, 0, 10);
constraints.gridy = 0;
createFrame.add(mainPanel, constraints);
int width = 400, height = 400;
createFrame.setSize(width, height);
createFrame.pack();
createFrame.setLocationRelativeTo(null);
try {
createFrame.setVisible(true);
} catch (Throwable t) {
// ignore
// some systems don't support this method, for example IKVM
// however it still works
}
try {
// ensure this window is in front of the browser
createFrame.setAlwaysOnTop(true);
createFrame.setAlwaysOnTop(false);
} catch (Throwable t) {
// ignore
}
}
private void createDatabase() {
if (web == null || createFrame == null) {
return;
}
String path = pathField.getText(), user = userField.getText(), password = passwordField.getText(),
passwordConfirmation = passwordConfirmationField.getText();
if (!password.equals(passwordConfirmation)) {
errorArea.setForeground(Color.RED);
errorArea.setText("Passwords don't match");
return;
}
if (password.isEmpty()) {
errorArea.setForeground(Color.RED);
errorArea.setText("Specify a password");
return;
}
String url = "jdbc:h2:" + path;
try {
new JdbcConnection(url, null, user, password, false).close();
errorArea.setForeground(new Color(0, 0x99, 0));
errorArea.setText("Database was created successfully.\n\n"
+ "JDBC URL for H2 Console:\n"
+ url);
} catch (Exception ex) {
errorArea.setForeground(Color.RED);
errorArea.setText(ex.getMessage());
}
}
/**
* INTERNAL
*/
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if ("exit".equals(command)) {
shutdown();
} else if ("console".equals(command)) {
startBrowser();
} else if ("showCreate".equals(command)) {
showCreateDatabase();
} else if ("status".equals(command)) {
showStatusWindow();
} else {
// for some reason, IKVM ignores setActionCommand
if (startBrowser == e.getSource()) {
startBrowser();
} else if (createButton == e.getSource()) {
createDatabase();
}
}
}
/**
* INTERNAL
*/
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
startBrowser();
}
}
/**
* INTERNAL
*/
@Override
public void mouseEntered(MouseEvent e) {
// nothing to do
}
/**
* INTERNAL
*/
@Override
public void mouseExited(MouseEvent e) {
// nothing to do
}
/**
* INTERNAL
*/
@Override
public void mousePressed(MouseEvent e) {
// nothing to do
}
/**
* INTERNAL
*/
@Override
public void mouseReleased(MouseEvent e) {
// nothing to do
}
/**
* INTERNAL
*/
@Override
public void windowClosing(WindowEvent e) {
if (trayIconUsed) {
Window window = e.getWindow();
if (window == statusFrame) {
statusFrame.dispose();
statusFrame = null;
} else if (window == createFrame) {
createFrame.dispose();
createFrame = null;
}
} else {
shutdown();
}
}
/**
* INTERNAL
*/
@Override
public void windowActivated(WindowEvent e) {
// nothing to do
}
/**
* INTERNAL
*/
@Override
public void windowClosed(WindowEvent e) {
// nothing to do
}
/**
* INTERNAL
*/
@Override
public void windowDeactivated(WindowEvent e) {
// nothing to do
}
/**
* INTERNAL
*/
@Override
public void windowDeiconified(WindowEvent e) {
// nothing to do
}
/**
* INTERNAL
*/
@Override
public void windowIconified(WindowEvent e) {
// nothing to do
}
/**
* INTERNAL
*/
@Override
public void windowOpened(WindowEvent e) {
// nothing to do
}
}