/*
* MySqlGui.java, 2006-04-01
*
* This file is part of xtnd-commons.
*
* Copyright © 2006 Johan Cwiklinski
*
* File : MySqlGui.java
* Author's email : johan@x-tnd.be
* Author's Website : http://ulysses.fr
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
package be.xtnd.commons.gui;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.WindowConstants;
import javax.swing.text.Position;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import be.xtnd.commons.db.Database;
import be.xtnd.commons.db.mysql.Mysql2Sql;
import be.xtnd.commons.i18n.CommonsI18n;
import be.xtnd.commons.utils.SQLFilter;
import be.xtnd.commons.utils.UtilsChooser;
import be.xtnd.commons.utils.XMLFilter;
import com.jeta.forms.components.panel.FormPanel;
import com.jeta.forms.components.separator.TitledSeparator;
/**
* @author Johan Cwiklinski
* @since 2006-04-01
*/
public class MySqlGui{
private Databases databases;
private String host_value, port_value, user_value, passe_value, provider_name,
sql_provider, sql_server, args_value, db_name;
private JTextField host, port, user, args, create,component, create_user;
private JPasswordField passe, create_password;
private JButton connect, select, quit, create_btn, export;
private JCheckBox enable_user;
private JTree tree;
private Database db;
static Logger logger = Logger.getLogger(MySqlGui.class.getName());
/**
* Default constructor
*/
public MySqlGui(){
PropertyConfigurator.configure(ClassLoader.getSystemResource("be/xtnd/commons/log4j.properties"));
}
/**
*
* @param c <code>JTextField</code>
*/
public MySqlGui(JTextField c){
this();
this.component = c;
}
/**
*
* @param c <code>JTextField</code>
* @param params String[]
*/
public MySqlGui(JTextField c, String[] params){
this(c);
this.host_value = params[0];
this.port_value = params[1];
this.user_value = params[2];
this.passe_value = params[3];
this.sql_provider = params[4];
this.provider_name = params[5];
this.sql_server = params[6];
this.args_value = params[7];
if ( connect() ) {
databases = new Databases();
}
}
private boolean connect(){
db = new Database(this.provider_name, this.sql_server, this.user_value,
this.passe_value, this.sql_provider);
/** FIXME: errors are already handled into {@link MysqlErrors}, we should relay on that to avoid duplicated code */
if(db.getErrCode()==1045){ //access denied
Object[] args = {db.getSql_server(), db.getSql_user(), (db.hasSql_password())?CommonsI18n.tr("yes"):CommonsI18n.tr("no")};
JOptionPane.showMessageDialog(
databases,
CommonsI18n.tr("<html>Database connection failed.<br>User or password is probably wrong.<br><br><b><u>Informations:</u></b><br><b>Server:</b> {0}<br><b>User:</b> {1}<br><b>Using password:</b> {2}</html>", args),
CommonsI18n.tr("Access denied"),
JOptionPane.ERROR_MESSAGE+JOptionPane.OK_OPTION);
return false;
}
if(db.getErrCode()==-10){ //manually defined UnknownHostException
Object[] args = {this.host_value};
JOptionPane.showMessageDialog(
databases,
CommonsI18n.tr("<html>Specified database host, \"<b>{0}</b>\", cannot be found.<br><br>Check if it was spelled correctly.<br>Also check your network connection.<br><br>Do you want to go to the configuration to fix the problem?</html>", args),
CommonsI18n.tr("Unknow host"),
JOptionPane.ERROR_MESSAGE+JOptionPane.OK_OPTION);
return false;
}
return true;
}
/**
* @author Johan Cwiklinski
* @since 2006-04-01
*/
public class Databases extends EscapeJFrame{
private static final long serialVersionUID = -3692770075432977552L;
private TitledSeparator title, db_title, export_title;
private JLabel host_label, port_label, user_label, passe_label,
args_label, create_label, create_user_label, create_password_label;
private JRadioButton xml_export, sql_export;
private ButtonGroup btn_group;
private JCheckBox structure, datas;
/**
* Default constructor
*/
public Databases(){
super();
super.setLocationRelativeTo(this.getParent());
PropertyConfigurator.configure(ClassLoader.getSystemResource("be/xtnd/db_updater/log4j.properties"));
FormPanel pane = new FormPanel( "be/xtnd/commons/gui/descriptions/sql_databases.jfrm" );
title = (TitledSeparator)pane.getComponentByName("title");
title.setText(CommonsI18n.tr("Browse databases"));
db_title = (TitledSeparator)pane.getComponentByName("db_title");
db_title.setText(CommonsI18n.tr("Database creation (root only)"));
host_label = pane.getLabel("host_label");
host_label.setText(CommonsI18n.tr("Host"));
host = pane.getTextField("host");
host.setText(host_value);
port_label = pane.getLabel("port_label");
port_label.setText(CommonsI18n.tr("Port"));
port = pane.getTextField("port");
port.setText(port_value);
user_label = pane.getLabel("user_label");
user_label.setText(CommonsI18n.tr("User name"));
user = pane.getTextField("user");
user.setText(user_value);
passe_label = pane.getLabel("passe_label");
passe_label.setText(CommonsI18n.tr("Password"));
passe = (JPasswordField)pane.getComponentByName("passe");
passe.setText(passe_value);
args_label = pane.getLabel("args_label");
args_label.setText(CommonsI18n.tr("Arguments"));
args = pane.getTextField("args");
args.setText(args_value);
connect = (JButton) pane.getButton("connect");
connect.setText(CommonsI18n.trc("Connection button (text)", "Connection"));
connect.setToolTipText(CommonsI18n.trc("Connection button (tooltip)", "Connection to the database with parameters you've entered"));
connect.setMnemonic(CommonsI18n.trc("Connection button (mnemonic)", "o").charAt(0));
connect.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
host_value = host.getText();
port_value = port.getText();
user_value = user.getText();
passe_value = new String(passe.getPassword());
args_value = args.getText();
sql_server = buildSqlServer();
connect();
initTree(tree);
}
});
select = (JButton) pane.getButton("select");
select.setText(CommonsI18n.trc("Select button (text)", "Select"));
select.setToolTipText(CommonsI18n.trc("Select button (tooltip)", "Choose a database in tree"));
select.setMnemonic(CommonsI18n.trc("Select button (mnemonic)", "s").charAt(0));
select.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
TreePath[] paths = tree.getSelectionPaths();
component.setText(paths[0].getLastPathComponent().toString());
dispose();
}
});
quit = (JButton) pane.getButton("quit");
quit.setText(CommonsI18n.trc("Close button (text)", "Close"));
quit.setToolTipText(CommonsI18n.trc("Close button (tooltip)", "Close window without selecting any database"));
quit.setMnemonic(CommonsI18n.trc("Close button (mnemonic)", "c").charAt(0));
quit.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
db.disconnect();
dispose();
}
});
tree = pane.getTree("databases");
initTree(tree);
create_label = pane.getLabel("create_label");
create_label.setText(CommonsI18n.tr("Enter a name"));
create = pane.getTextField("create");
create_user_label = pane.getLabel("create_user_label");
create_user_label.setText(CommonsI18n.tr("User name"));
create_user_label.setEnabled(false);
create_user = pane.getTextField("create_user");
create_user.setEnabled(false);
create_password_label = pane.getLabel("create_password_label");
create_password_label.setText(CommonsI18n.tr("Password"));
create_password_label.setEnabled(false);
create_password = (JPasswordField)pane.getComponentByName("create_password");
create_password.setEnabled(false);
enable_user = pane.getCheckBox("enable_user");
enable_user.setText(CommonsI18n.tr("Save user"));
enable_user.setToolTipText(CommonsI18n.tr("If active, user and its associated password will be saved.\nUser will get utilisation permissions on the database."));
enable_user.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
create_user_label.setEnabled(enable_user.isSelected());
create_user.setEnabled(enable_user.isSelected());
create_password_label.setEnabled(enable_user.isSelected());
create_password.setEnabled(enable_user.isSelected());
}
});
create_btn = (JButton)pane.getComponentByName("create_btn");
create_btn.setText(CommonsI18n.tr("Create database"));
create_btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
if(verifEntrees()){
connect();
ArrayList<String> createQueries = createDatabase();
Iterator<String> i = createQueries.iterator();
while(i.hasNext()){
String qry = (String)i.next();
try {
logger.debug("Query : "+qry);
System.out.println("req. : " + qry);
db.execUpdate(qry);
} catch (SQLException e1) {
logger.fatal("SQLException while create database : "+e1.getMessage()+" (code "+e1.getErrorCode()+")");
logger.debug("Message was : "+e1.getMessage());
logger.debug("Error Code : "+e1.getErrorCode());
e1.printStackTrace();
}
}
initTree(tree);
int startRow = 0;
String prefix = create.getText();
TreePath path = tree.getNextMatch(prefix, startRow, Position.Bias.Forward);
tree.setSelectionPath(path);
}
}
});
export_title = (TitledSeparator)pane.getComponentByName("export_title");
export_title.setText(CommonsI18n.trc("Title", "Export"));
xml_export = pane.getRadioButton("xml_export");
xml_export.setText(CommonsI18n.tr("XML File"));
sql_export = pane.getRadioButton("sql_export");
sql_export.setText(CommonsI18n.tr("SQL File"));
sql_export.setSelected(true);
btn_group = new ButtonGroup();
btn_group.add(xml_export);
btn_group.add(sql_export);
structure = pane.getCheckBox("structure");
structure.setText(CommonsI18n.tr("Structure"));
datas = pane.getCheckBox("datas");
datas.setText(CommonsI18n.tr("Datas"));
export = (JButton)pane.getButton("export");
export.setText(CommonsI18n.trc("Button", "Export"));
export.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
TreePath[] paths = tree.getSelectionPaths();
if(paths==null || paths.length==0){
JOptionPane.showMessageDialog(
MainGui.desktop,
CommonsI18n.tr("No database has been selected.\nPlease choose one before anything."),
CommonsI18n.tr("Error!"),
JOptionPane.ERROR_MESSAGE);
logger.debug("No database selected for export");
}else{
db_name = paths[0].getLastPathComponent().toString();
Mysql2Sql msql = new Mysql2Sql(new Database(
provider_name,
buildSqlServer(),
user_value,
passe_value,
sql_provider),
structure.isSelected(),
datas.isSelected());
String datas = msql.dump((xml_export.isSelected())?Mysql2Sql.XML_MODE:Mysql2Sql.SQL_MODE);
JFileChooser fc = new JFileChooser();
File f = null;
try {
f = new File(new File(System.getProperty("user.dir")).getCanonicalPath());
} catch (IOException e1) {
e1.printStackTrace();
}
fc.setCurrentDirectory(f);
fc.addChoosableFileFilter((xml_export.isSelected())?new XMLFilter():new SQLFilter());
int returnVal = fc.showOpenDialog(databases);
if(returnVal == JFileChooser.APPROVE_OPTION){
StringBuffer path = new StringBuffer();
path.append(fc.getCurrentDirectory());
path.append(System.getProperty("file.separator"));
path.append(UtilsChooser.removeExtension(fc.getSelectedFile()));
path.append(".");
path.append((xml_export.isSelected())?Mysql2Sql.XML_MODE:Mysql2Sql.SQL_MODE);
try {
BufferedWriter out = new BufferedWriter(new FileWriter(path.toString()));
out.write(datas);
out.close();
logger.info("File "+path.toString()+" successfully writed");
} catch (IOException e2) {
logger.error("IOException writting file "+e2);
e2.printStackTrace();
}
}
}
}
});
this.getContentPane().add(pane);
this.pack();
this.setTitle(CommonsI18n.tr("Browse databases"));
this.setSize(new Dimension(550,this.getHeight()));
this.setLocationRelativeTo(this.getParent());
this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
this.setVisible(true);
}
}
private String buildSqlServer(){
StringBuffer sb = new StringBuffer("jdbc:"+provider_name+":");
sb.append("//");
if(host_value.length()>0){
sb.append(host_value);
if(port_value.length()>0) sb.append(":"+port_value);
sb.append("/");
}
if(db_name!=null)
sb.append(db_name);
if(args_value.length()>0){
sb.append(args_value);
}
return sb.toString();
}
private boolean verifEntrees(){
boolean valid = true;
StringBuffer sb = new StringBuffer();
sb.append(CommonsI18n.tr("The following are required:"));
if(create.getText().trim().equals("")){
sb.append("\n- "+CommonsI18n.tr("database name"));
if(valid) create.requestFocus();
valid = false;
}
if(enable_user.isSelected() && create_user.getText().trim().equals("")){
sb.append("\n- "+CommonsI18n.tr("SQL user name"));
if(valid) create_user.requestFocus();
valid = false;
}
if(!valid){
JOptionPane.showMessageDialog(MainGui.desktop, sb.toString(),
CommonsI18n.tr("Error!"),JOptionPane.ERROR_MESSAGE);
}
return valid;
}
/**
*
* @param tree
*/
public void initTree(JTree tree){
//Create the nodes.
DefaultMutableTreeNode top =
new DefaultMutableTreeNode(user.getText()+"@"+host.getText()+":"+port.getText());
createNodes(top);
ImageIcon icon = new ImageIcon(ClassLoader.getSystemResource("be/xtnd/icons/server.png"));
ImageIcon leafIcon = new ImageIcon(ClassLoader.getSystemResource("be/xtnd/icons/database.png"));
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
model.setRoot(top);
DefaultTreeCellRenderer renderer =
new DefaultTreeCellRenderer();
if (icon != null) {
renderer.setOpenIcon(icon);
renderer.setClosedIcon(icon);
}
if(leafIcon != null){
renderer.setLeafIcon(leafIcon);
}
tree.setCellRenderer(renderer);
tree.setRowHeight(0);
}
/**
* Create nodes with found databases
*
* @param top root node
*/
private void createNodes(DefaultMutableTreeNode top) {
DefaultMutableTreeNode databases = null;
try {
ResultSet rs = db.execQuery("SHOW DATABASES");
rs.beforeFirst();
while(rs.next()){
databases = new DefaultMutableTreeNode(new DbInfo(rs.getString("Database")));
top.add(databases);
}
} catch (SQLException e) {
logger.error("SQLException showing databases "+e.getMessage()+"(code "+e.getErrorCode()+")");
}
}
/**
* Build queries required to create database, user and
* its permissions.
*
* @return ArrayList queries to execute
*/
private ArrayList<String> createDatabase(){
ArrayList<String> list = new ArrayList<String>();
StringBuffer sb = new StringBuffer();
list.add("CREATE DATABASE "+create.getText());
if(!create_user.getText().trim().equals("")){
sb.append("GRANT ALL ON "+create.getText()+".* TO '"+create_user.getText()+"'@'"+host.getText()+"'");
if(create_password.getPassword().length>0)
sb.append(" IDENTIFIED BY '"+new String(create_password.getPassword())+"'");
list.add(sb.toString());
}
return list;
}
private class DbInfo {
/** */
public String dbName;
/**
*
* @param dbname
*/
public DbInfo(String dbname){
dbName = dbname;
}
/**
* @return String
*/
public String toString(){
return dbName;
}
}
}