You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by an...@apache.org on 2015/10/13 05:28:16 UTC

[15/18] ignite git commit: IGNITE-843 Split schema-import

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd50bdf8/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
index 4f419e6..cbcddc2 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
@@ -22,16 +22,11 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.net.URL;
-import java.net.URLClassLoader;
 import java.sql.Connection;
-import java.sql.Driver;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -45,6 +40,7 @@ import javafx.beans.value.ObservableValue;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 import javafx.concurrent.Task;
+import javafx.embed.swing.SwingFXUtils;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
 import javafx.geometry.Insets;
@@ -81,34 +77,7 @@ import org.apache.ignite.schema.model.PojoDescriptor;
 import org.apache.ignite.schema.model.PojoField;
 import org.apache.ignite.schema.model.SchemaDescriptor;
 import org.apache.ignite.schema.parser.DatabaseMetadataParser;
-
-import static javafx.embed.swing.SwingFXUtils.fromFXImage;
-import static org.apache.ignite.schema.ui.Controls.booleanColumn;
-import static org.apache.ignite.schema.ui.Controls.borderPane;
-import static org.apache.ignite.schema.ui.Controls.button;
-import static org.apache.ignite.schema.ui.Controls.buttonsPane;
-import static org.apache.ignite.schema.ui.Controls.checkBox;
-import static org.apache.ignite.schema.ui.Controls.comboBox;
-import static org.apache.ignite.schema.ui.Controls.customColumn;
-import static org.apache.ignite.schema.ui.Controls.hBox;
-import static org.apache.ignite.schema.ui.Controls.image;
-import static org.apache.ignite.schema.ui.Controls.imageView;
-import static org.apache.ignite.schema.ui.Controls.label;
-import static org.apache.ignite.schema.ui.Controls.list;
-import static org.apache.ignite.schema.ui.Controls.paneEx;
-import static org.apache.ignite.schema.ui.Controls.passwordField;
-import static org.apache.ignite.schema.ui.Controls.progressIndicator;
-import static org.apache.ignite.schema.ui.Controls.scene;
-import static org.apache.ignite.schema.ui.Controls.splitPane;
-import static org.apache.ignite.schema.ui.Controls.stackPane;
-import static org.apache.ignite.schema.ui.Controls.tableColumn;
-import static org.apache.ignite.schema.ui.Controls.tableView;
-import static org.apache.ignite.schema.ui.Controls.text;
-import static org.apache.ignite.schema.ui.Controls.textColumn;
-import static org.apache.ignite.schema.ui.Controls.textField;
-import static org.apache.ignite.schema.ui.Controls.titledPane;
-import static org.apache.ignite.schema.ui.Controls.tooltip;
-import static org.apache.ignite.schema.ui.Controls.vBox;
+import org.apache.ignite.schema.parser.DbMetadataReader;
 
 /**
  * Schema Import utility application.
@@ -117,68 +86,6 @@ import static org.apache.ignite.schema.ui.Controls.vBox;
 public class SchemaImportApp extends Application {
     /** Logger. */
     private static final Logger log = Logger.getLogger(SchemaImportApp.class.getName());
-
-    /** Presets for database settings. */
-    private static class Preset {
-        /** Name in preferences. */
-        private String pref;
-
-        /** RDBMS name to show on screen. */
-        private String name;
-
-        /** Path to JDBC driver jar. */
-        private String jar;
-
-        /** JDBC driver class name. */
-        private String drv;
-
-        /** JDBC URL. */
-        private String url;
-
-        /** User name. */
-        private String user;
-
-        /**
-         * Preset constructor.
-         *
-         * @param pref Name in preferences.
-         * @param name RDBMS name to show on screen.
-         * @param jar Path to JDBC driver jar..
-         * @param drv JDBC driver class name.
-         * @param url JDBC URL.
-         * @param user User name.
-         */
-        Preset(String pref, String name, String jar, String drv, String url, String user) {
-            this.pref = pref;
-            this.name = name;
-            this.jar = jar;
-            this.drv = drv;
-            this.url = url;
-            this.user = user;
-        }
-
-        /** {@inheritDoc} */
-        @Override public String toString() {
-            return name;
-        }
-    }
-
-    /** Default presets for popular databases. */
-    private final Preset[] presets = {
-        new Preset("h2", "H2 Database", "h2.jar", "org.h2.Driver", "jdbc:h2:[database]", "sa"),
-        new Preset("db2", "DB2", "db2jcc4.jar", "com.ibm.db2.jcc.DB2Driver", "jdbc:db2://[host]:[port]/[database]",
-            "db2admin"),
-        new Preset("oracle", "Oracle", "ojdbc6.jar", "oracle.jdbc.OracleDriver",
-            "jdbc:oracle:thin:@[host]:[port]:[database]", "system"),
-        new Preset("mysql", "MySQL", "mysql-connector-java-5-bin.jar", "com.mysql.jdbc.Driver",
-            "jdbc:mysql://[host]:[port]/[database]", "root"),
-        new Preset("mssql", "Microsoft SQL Server", "sqljdbc41.jar", "com.microsoft.sqlserver.jdbc.SQLServerDriver",
-            "jdbc:sqlserver://[host]:[port][;databaseName=database]", "sa"),
-        new Preset("postgresql", "PostgreSQL", "postgresql-9.3.jdbc4.jar", "org.postgresql.Driver",
-            "jdbc:postgresql://[host]:[port]/[database]", "sa"),
-        new Preset("custom", "Custom server...", "custom-jdbc.jar", "org.custom.Driver", "jdbc:custom", "sa")
-    };
-
     /** */
     private static final String PREF_WINDOW_X = "window.x";
     /** */
@@ -187,7 +94,6 @@ public class SchemaImportApp extends Application {
     private static final String PREF_WINDOW_WIDTH = "window.width";
     /** */
     private static final String PREF_WINDOW_HEIGHT = "window.height";
-
     /** */
     private static final String PREF_JDBC_DB_PRESET = "jdbc.db.preset";
     /** */
@@ -198,151 +104,154 @@ public class SchemaImportApp extends Application {
     private static final String PREF_JDBC_URL = "jdbc.url";
     /** */
     private static final String PREF_JDBC_USER = "jdbc.user";
-
     /** */
     private static final String PREF_OUT_FOLDER = "out.folder";
-
     /** */
     private static final String PREF_POJO_PACKAGE = "pojo.package";
     /** */
     private static final String PREF_POJO_INCLUDE = "pojo.include";
     /** */
     private static final String PREF_POJO_CONSTRUCTOR = "pojo.constructor";
-
     /** */
     private static final String PREF_XML_SINGLE = "xml.single";
-
     /** */
     private static final String PREF_NAMING_PATTERN = "naming.pattern";
     /** */
     private static final String PREF_NAMING_REPLACE = "naming.replace";
+    /** Empty POJO fields model. */
+    private static final ObservableList<PojoField> NO_FIELDS = FXCollections.emptyObservableList();
+    /** Default presets for popular databases. */
+    private final Preset[] presets = {
+        new Preset("h2", "H2 Database", "h2.jar", "org.h2.Driver", "jdbc:h2:[database]", "sa"),
+        new Preset("db2", "DB2", "db2jcc4.jar", "com.ibm.db2.jcc.DB2Driver", "jdbc:db2://[host]:[port]/[database]",
+            "db2admin"),
+        new Preset("oracle", "Oracle", "ojdbc6.jar", "oracle.jdbc.OracleDriver",
+            "jdbc:oracle:thin:@[host]:[port]:[database]", "system"),
+        new Preset("mysql", "MySQL", "mysql-connector-java-5-bin.jar", "com.mysql.jdbc.Driver",
+            "jdbc:mysql://[host]:[port]/[database]", "root"),
+        new Preset("mssql", "Microsoft SQL Server", "sqljdbc41.jar", "com.microsoft.sqlserver.jdbc.SQLServerDriver",
+            "jdbc:sqlserver://[host]:[port][;databaseName=database]", "sa"),
+        new Preset("postgresql", "PostgreSQL", "postgresql-9.3.jdbc4.jar", "org.postgresql.Driver",
+            "jdbc:postgresql://[host]:[port]/[database]", "sa"),
+        new Preset("custom", "Custom server...", "custom-jdbc.jar", "org.custom.Driver", "jdbc:custom", "sa")
+    };
+    /** Application preferences. */
+    private final Properties prefs = new Properties();
+    /** File path for storing on local file system. */
+    private final File prefsFile = new File(System.getProperty("user.home"), ".ignite-schema-import");
+    /** */
+    private final ExecutorService exec = Executors.newSingleThreadExecutor(new ThreadFactory() {
+        @Override public Thread newThread(Runnable r) {
+            Thread t = new Thread(r, "ignite-schema-import-worker");
+
+            t.setDaemon(true);
 
+            return t;
+        }
+    });
     /** */
     private Stage owner;
-
     /** */
     private BorderPane rootPane;
-
     /** Header pane. */
     private BorderPane hdrPane;
-
     /** */
     private HBox dbIcon;
-
     /** */
     private HBox genIcon;
-
     /** */
     private Label titleLb;
-
     /** */
     private Label subTitleLb;
-
     /** */
     private Button prevBtn;
-
     /** */
     private Button nextBtn;
-
     /** */
     private ComboBox<Preset> rdbmsCb;
-
     /** */
     private TextField jdbcDrvJarTf;
-
     /** */
     private TextField jdbcDrvClsTf;
-
     /** */
     private TextField jdbcUrlTf;
-
     /** */
     private TextField userTf;
-
     /** */
     private PasswordField pwdTf;
-
     /** */
     private ComboBox<String> parseCb;
-
     /** */
     private ListView<SchemaDescriptor> schemaLst;
-
     /** */
     private GridPaneEx connPnl;
-
     /** */
     private StackPane connLayerPnl;
-
     /** */
     private TableView<PojoDescriptor> pojosTbl;
-
     /** */
     private TableView<PojoField> fieldsTbl;
-
     /** */
     private Node curTbl;
-
     /** */
     private TextField outFolderTf;
-
     /** */
     private TextField pkgTf;
-
     /** */
     private CheckBox pojoConstructorCh;
-
     /** */
     private CheckBox pojoIncludeKeysCh;
-
     /** */
     private CheckBox xmlSingleFileCh;
-
     /** */
     private TextField regexTf;
-
     /** */
     private TextField replaceTf;
-
     /** */
     private GridPaneEx genPnl;
-
     /** */
     private StackPane genLayerPnl;
-
     /** */
     private ProgressIndicator pi;
-
+    /** */
     private ObservableList<SchemaDescriptor> schemas = FXCollections.emptyObservableList();
-
     /** List with POJOs descriptors. */
     private ObservableList<PojoDescriptor> pojos = FXCollections.emptyObservableList();
-
     /** Currently selected POJO. */
     private PojoDescriptor curPojo;
 
-    /** */
-    private final Map<String, Driver> drivers = new HashMap<>();
-
-    /** Application preferences. */
-    private final Properties prefs = new Properties();
+    /**
+     * Schema Import utility launcher.
+     *
+     * @param args Command line arguments passed to the application.
+     */
+    public static void main(String[] args) {
+        // Workaround for JavaFX ugly text AA.
+        System.setProperty("prism.lcdtext", "false");
+        System.setProperty("prism.text", "t2k");
 
-    /** File path for storing on local file system. */
-    private final File prefsFile = new File(System.getProperty("user.home"), ".ignite-schema-import");
+        // Workaround for AWT + JavaFX: we should initialize AWT before JavaFX.
+        java.awt.Toolkit.getDefaultToolkit();
 
-    /** Empty POJO fields model. */
-    private static final ObservableList<PojoField> NO_FIELDS = FXCollections.emptyObservableList();
+        // Workaround for JavaFX + Mac OS dock icon.
+        if (System.getProperty("os.name").toLowerCase().contains("mac os")) {
+            System.setProperty("javafx.macosx.embedded", "true");
 
-    /** */
-    private final ExecutorService exec = Executors.newSingleThreadExecutor(new ThreadFactory() {
-        @Override public Thread newThread(Runnable r) {
-            Thread t = new Thread(r, "ignite-schema-import-worker");
+            try {
+                Class<?> appCls = Class.forName("com.apple.eawt.Application");
 
-            t.setDaemon(true);
+                Object osxApp = appCls.getDeclaredMethod("getApplication").invoke(null);
 
-            return t;
+                appCls.getDeclaredMethod("setDockIconImage", java.awt.Image.class)
+                    .invoke(osxApp, SwingFXUtils.fromFXImage(Controls.image("ignite", 128), null));
+            }
+            catch (Exception ignore) {
+                // No-op.
+            }
         }
-    });
+
+        launch(args);
+    }
 
     /**
      * Lock UI before start long task.
@@ -412,7 +321,7 @@ public class SchemaImportApp extends Application {
         if (!pwd.isEmpty())
             jdbcInfo.put("password", pwd);
 
-        return connect(jdbcDrvJarPath, jdbcDrvCls, jdbcUrl, jdbcInfo);
+        return DbMetadataReader.getInstance().connect(jdbcDrvJarPath, jdbcDrvCls, jdbcUrl, jdbcInfo);
     }
 
     /**
@@ -478,7 +387,7 @@ public class SchemaImportApp extends Application {
 
                     prevBtn.setDisable(false);
                     nextBtn.setText("Generate");
-                    tooltip(nextBtn, "Generate XML and POJO files");
+                    Controls.tooltip(nextBtn, "Generate XML and POJO files");
                 }
                 finally {
                     unlockUI(connLayerPnl, connPnl, nextBtn);
@@ -701,15 +610,16 @@ public class SchemaImportApp extends Application {
      * @return Header pane with title label.
      */
     private BorderPane createHeaderPane() {
-        dbIcon = hBox(0, true, imageView("data_connection", 48));
-        genIcon = hBox(0, true, imageView("text_tree", 48));
+        dbIcon = Controls.hBox(0, true, Controls.imageView("data_connection", 48));
+        genIcon = Controls.hBox(0, true, Controls.imageView("text_tree", 48));
 
-        titleLb = label("");
+        titleLb = Controls.label("");
         titleLb.setId("banner");
 
-        subTitleLb = label("");
+        subTitleLb = Controls.label("");
 
-        BorderPane bp = borderPane(null, vBox(5, titleLb, subTitleLb), null, dbIcon, hBox(0, true, imageView("ignite", 48)));
+        BorderPane bp = Controls.borderPane(null, Controls.vBox(5, titleLb, subTitleLb), null, dbIcon,
+            Controls.hBox(0, true, Controls.imageView("ignite", 48)));
         bp.setId("banner");
 
         return bp;
@@ -719,19 +629,19 @@ public class SchemaImportApp extends Application {
      * @return Panel with control buttons.
      */
     private Pane createButtonsPane() {
-        prevBtn = button("Prev", "Go to \"Database connection\" page", new EventHandler<ActionEvent>() {
+        prevBtn = Controls.button("Prev", "Go to \"Database connection\" page", new EventHandler<ActionEvent>() {
             @Override public void handle(ActionEvent evt) {
                 prev();
             }
         });
 
-        nextBtn = button("Next", "Go to \"POJO and XML generation\" page", new EventHandler<ActionEvent>() {
+        nextBtn = Controls.button("Next", "Go to \"POJO and XML generation\" page", new EventHandler<ActionEvent>() {
             @Override public void handle(ActionEvent evt) {
                 next();
             }
         });
 
-        return buttonsPane(Pos.BOTTOM_RIGHT, true, prevBtn, nextBtn);
+        return Controls.buttonsPane(Pos.BOTTOM_RIGHT, true, prevBtn, nextBtn);
     }
 
     /**
@@ -762,7 +672,7 @@ public class SchemaImportApp extends Application {
 
         prevBtn.setDisable(true);
         nextBtn.setText("Next");
-        tooltip(nextBtn, "Go to \"XML and POJO generation\" page");
+        Controls.tooltip(nextBtn, "Go to \"XML and POJO generation\" page");
     }
 
     /**
@@ -805,57 +715,12 @@ public class SchemaImportApp extends Application {
     }
 
     /**
-     * Connect to database.
-     *
-     * @param jdbcDrvJarPath Path to JDBC driver.
-     * @param jdbcDrvCls JDBC class name.
-     * @param jdbcUrl JDBC connection URL.
-     * @param jdbcInfo Connection properties.
-     * @return Connection to database.
-     * @throws SQLException if connection failed.
-     */
-    private Connection connect(String jdbcDrvJarPath, String jdbcDrvCls, String jdbcUrl, Properties jdbcInfo)
-        throws SQLException {
-        Driver drv = drivers.get(jdbcDrvCls);
-
-        if (drv == null) {
-            if (jdbcDrvJarPath.isEmpty())
-                throw new IllegalStateException("Driver jar file name is not specified.");
-
-            File drvJar = new File(jdbcDrvJarPath);
-
-            if (!drvJar.exists())
-                throw new IllegalStateException("Driver jar file is not found.");
-
-            try {
-                URL u = new URL("jar:" + drvJar.toURI() + "!/");
-
-                URLClassLoader ucl = URLClassLoader.newInstance(new URL[] {u});
-
-                drv = (Driver)Class.forName(jdbcDrvCls, true, ucl).newInstance();
-
-                drivers.put(jdbcDrvCls, drv);
-            }
-            catch (Exception e) {
-                throw new IllegalStateException(e);
-            }
-        }
-
-        Connection conn = drv.connect(jdbcUrl, jdbcInfo);
-
-        if (conn == null)
-            throw new IllegalStateException("Connection was not established (JDBC driver returned null value).");
-
-        return conn;
-    }
-
-    /**
      * Create connection pane with controls.
      *
      * @return Pane with connection controls.
      */
     private Pane createConnectionPane() {
-        connPnl = paneEx(10, 10, 0, 10);
+        connPnl = Controls.paneEx(10, 10, 0, 10);
 
         connPnl.addColumn();
         connPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
@@ -864,18 +729,18 @@ public class SchemaImportApp extends Application {
         connPnl.addRows(9);
         connPnl.addRow(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
 
-        connPnl.add(text("This utility is designed to automatically generate configuration XML files and" +
+        connPnl.add(Controls.text("This utility is designed to automatically generate configuration XML files and" +
             " POJO classes from database schema information.", 550), 3);
 
         connPnl.wrap();
 
-        GridPaneEx presetPnl = paneEx(0, 0, 0, 0);
+        GridPaneEx presetPnl = Controls.paneEx(0, 0, 0, 0);
         presetPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
         presetPnl.addColumn();
 
-        rdbmsCb = presetPnl.add(comboBox("Select database server to get predefined settings", presets));
+        rdbmsCb = presetPnl.add(Controls.comboBox("Select database server to get predefined settings", presets));
 
-        presetPnl.add(button("Save preset", "Save current settings in preferences", new EventHandler<ActionEvent>() {
+        presetPnl.add(Controls.button("Save preset", "Save current settings in preferences", new EventHandler<ActionEvent>() {
             @Override public void handle(ActionEvent evt) {
                 Preset preset = rdbmsCb.getSelectionModel().getSelectedItem();
 
@@ -883,12 +748,12 @@ public class SchemaImportApp extends Application {
             }
         }));
 
-        connPnl.add(label("DB Preset:"));
+        connPnl.add(Controls.label("DB Preset:"));
         connPnl.add(presetPnl, 2);
 
-        jdbcDrvJarTf = connPnl.addLabeled("Driver JAR:", textField("Path to driver jar"));
+        jdbcDrvJarTf = connPnl.addLabeled("Driver JAR:", Controls.textField("Path to driver jar"));
 
-        connPnl.add(button("...", "Select JDBC driver jar or zip", new EventHandler<ActionEvent>() {
+        connPnl.add(Controls.button("...", "Select JDBC driver jar or zip", new EventHandler<ActionEvent>() {
             /** {@inheritDoc} */
             @Override public void handle(ActionEvent evt) {
                 FileChooser fc = new FileChooser();
@@ -916,9 +781,9 @@ public class SchemaImportApp extends Application {
             }
         }));
 
-        jdbcDrvClsTf = connPnl.addLabeled("JDBC Driver:", textField("Enter class name for JDBC driver"), 2);
+        jdbcDrvClsTf = connPnl.addLabeled("JDBC Driver:", Controls.textField("Enter class name for JDBC driver"), 2);
 
-        jdbcUrlTf = connPnl.addLabeled("JDBC URL:", textField("JDBC URL of the database connection string"), 2);
+        jdbcUrlTf = connPnl.addLabeled("JDBC URL:", Controls.textField("JDBC URL of the database connection string"), 2);
 
         rdbmsCb.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Preset>() {
             @Override public void changed(ObservableValue<? extends Preset> val, Preset oldVal, Preset newVal) {
@@ -929,34 +794,33 @@ public class SchemaImportApp extends Application {
             }
         });
 
-        userTf = connPnl.addLabeled("User:", textField("User name"), 2);
+        userTf = connPnl.addLabeled("User:", Controls.textField("User name"), 2);
 
-        pwdTf = connPnl.addLabeled("Password:", passwordField("User password"), 2);
+        pwdTf = connPnl.addLabeled("Password:", Controls.passwordField("User password"), 2);
 
-        parseCb = connPnl.addLabeled("Parse:", comboBox("Type of tables to parse", "Tables only", "Tables and Views"), 2);
+        parseCb = connPnl.addLabeled("Parse:", Controls.comboBox("Type of tables to parse", "Tables only", "Tables and Views"), 2);
 
-        GridPaneEx schemaPnl = paneEx(5, 5, 5, 5);
+        GridPaneEx schemaPnl = Controls.paneEx(5, 5, 5, 5);
         schemaPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
         schemaPnl.addColumn();
 
-        schemaLst = schemaPnl.add(list("Select schemas to load", new SchemaCell()));
+        schemaLst = schemaPnl.add(Controls.list("Select schemas to load", new SchemaCell()));
 
         schemaPnl.wrap();
 
-        schemaPnl.add(button("Load schemas", "Load schemas for specified database", new EventHandler<ActionEvent>() {
-            @Override
-            public void handle(ActionEvent evt) {
+        schemaPnl.add(Controls.button("Load schemas", "Load schemas for specified database", new EventHandler<ActionEvent>() {
+            @Override public void handle(ActionEvent evt) {
                 loadSchemas();
             }
         }));
 
-        TitledPane titledPnl = connPnl.add(titledPane("Schemas", schemaPnl, false), 3);
+        TitledPane titledPnl = connPnl.add(Controls.titledPane("Schemas", schemaPnl, false), 3);
 
         titledPnl.setExpanded(true);
 
         GridPaneEx.setValignment(titledPnl, VPos.TOP);
 
-        connLayerPnl = stackPane(connPnl);
+        connLayerPnl = Controls.stackPane(connPnl);
 
         return connLayerPnl;
     }
@@ -1020,7 +884,7 @@ public class SchemaImportApp extends Application {
      * Create generate pane with controls.
      */
     private void createGeneratePane() {
-        genPnl = paneEx(10, 10, 0, 10);
+        genPnl = Controls.paneEx(10, 10, 0, 10);
 
         genPnl.addColumn();
         genPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
@@ -1029,10 +893,10 @@ public class SchemaImportApp extends Application {
         genPnl.addRow(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
         genPnl.addRows(7);
 
-        TableColumn<PojoDescriptor, Boolean> useCol = customColumn("Schema / Table", "use",
+        TableColumn<PojoDescriptor, Boolean> useCol = Controls.customColumn("Schema / Table", "use",
             "If checked then this table will be used for XML and POJOs generation", PojoDescriptorCell.cellFactory());
 
-        TableColumn<PojoDescriptor, String> keyClsCol = textColumn("Key Class Name", "keyClassName", "Key class name",
+        TableColumn<PojoDescriptor, String> keyClsCol = Controls.textColumn("Key Class Name", "keyClassName", "Key class name",
             new TextColumnValidator<PojoDescriptor>() {
                 @Override public boolean valid(PojoDescriptor rowVal, String newVal) {
                     boolean valid = checkClassName(rowVal, newVal, true);
@@ -1044,7 +908,7 @@ public class SchemaImportApp extends Application {
                 }
             });
 
-        TableColumn<PojoDescriptor, String> valClsCol = textColumn("Value Class Name", "valueClassName", "Value class name",
+        TableColumn<PojoDescriptor, String> valClsCol = Controls.textColumn("Value Class Name", "valueClassName", "Value class name",
             new TextColumnValidator<PojoDescriptor>() {
                 @Override public boolean valid(PojoDescriptor rowVal, String newVal) {
                     boolean valid = checkClassName(rowVal, newVal, false);
@@ -1056,26 +920,26 @@ public class SchemaImportApp extends Application {
                 }
             });
 
-        pojosTbl = tableView("Tables not found in database", useCol, keyClsCol, valClsCol);
+        pojosTbl = Controls.tableView("Tables not found in database", useCol, keyClsCol, valClsCol);
 
-        TableColumn<PojoField, Boolean> useFldCol = customColumn("Use", "use",
+        TableColumn<PojoField, Boolean> useFldCol = Controls.customColumn("Use", "use",
             "Check to use this field for XML and POJO generation\n" +
-            "Note that NOT NULL columns cannot be unchecked", PojoFieldUseCell.cellFactory());
+                "Note that NOT NULL columns cannot be unchecked", PojoFieldUseCell.cellFactory());
         useFldCol.setMinWidth(50);
         useFldCol.setMaxWidth(50);
 
-        TableColumn<PojoField, Boolean> keyCol = booleanColumn("Key", "key",
+        TableColumn<PojoField, Boolean> keyCol = Controls.booleanColumn("Key", "key",
             "Check to include this field into key object");
 
-        TableColumn<PojoField, Boolean> akCol = booleanColumn("AK", "affinityKey",
+        TableColumn<PojoField, Boolean> akCol = Controls.booleanColumn("AK", "affinityKey",
             "Check to annotate key filed with @AffinityKeyMapped annotation in generated POJO class\n" +
-            "Note that a class can have only ONE key field annotated with @AffinityKeyMapped annotation");
+                "Note that a class can have only ONE key field annotated with @AffinityKeyMapped annotation");
 
-        TableColumn<PojoField, String> dbNameCol = tableColumn("DB Name", "dbName", "Field name in database");
+        TableColumn<PojoField, String> dbNameCol = Controls.tableColumn("DB Name", "dbName", "Field name in database");
 
-        TableColumn<PojoField, String> dbTypeNameCol = tableColumn("DB Type", "dbTypeName", "Field type in database");
+        TableColumn<PojoField, String> dbTypeNameCol = Controls.tableColumn("DB Type", "dbTypeName", "Field type in database");
 
-        TableColumn<PojoField, String> javaNameCol = textColumn("Java Name", "javaName", "Field name in POJO class",
+        TableColumn<PojoField, String> javaNameCol = Controls.textColumn("Java Name", "javaName", "Field name in POJO class",
             new TextColumnValidator<PojoField>() {
                 @Override public boolean valid(PojoField rowVal, String newVal) {
                     if (newVal.trim().isEmpty()) {
@@ -1097,25 +961,25 @@ public class SchemaImportApp extends Application {
                 }
             });
 
-        TableColumn<PojoField, String> javaTypeNameCol = customColumn("Java Type", "javaTypeName",
+        TableColumn<PojoField, String> javaTypeNameCol = Controls.customColumn("Java Type", "javaTypeName",
             "Field java type in POJO class", JavaTypeCell.cellFactory());
 
-        fieldsTbl = tableView("Select table to see table columns",
+        fieldsTbl = Controls.tableView("Select table to see table columns",
             useFldCol, keyCol, akCol, dbNameCol, dbTypeNameCol, javaNameCol, javaTypeNameCol);
 
-        genPnl.add(splitPane(pojosTbl, fieldsTbl, 0.6), 3);
+        genPnl.add(Controls.splitPane(pojosTbl, fieldsTbl, 0.6), 3);
 
-        final GridPaneEx keyValPnl = paneEx(0, 0, 0, 0);
+        final GridPaneEx keyValPnl = Controls.paneEx(0, 0, 0, 0);
         keyValPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
         keyValPnl.addColumn();
         keyValPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
         keyValPnl.addColumn();
 
-        pkgTf = genPnl.addLabeled("Package:", textField("Package that will be used for POJOs generation"), 2);
+        pkgTf = genPnl.addLabeled("Package:", Controls.textField("Package that will be used for POJOs generation"), 2);
 
-        outFolderTf = genPnl.addLabeled("Output Folder:", textField("Output folder for XML and POJOs files"));
+        outFolderTf = genPnl.addLabeled("Output Folder:", Controls.textField("Output folder for XML and POJOs files"));
 
-        genPnl.add(button("...", "Select output folder", new EventHandler<ActionEvent>() {
+        genPnl.add(Controls.button("...", "Select output folder", new EventHandler<ActionEvent>() {
             @Override public void handle(ActionEvent evt) {
                 DirectoryChooser dc = new DirectoryChooser();
 
@@ -1136,30 +1000,30 @@ public class SchemaImportApp extends Application {
             }
         }));
 
-        pojoIncludeKeysCh = genPnl.add(checkBox("Include key fields into value POJOs",
+        pojoIncludeKeysCh = genPnl.add(Controls.checkBox("Include key fields into value POJOs",
             "If selected then include key fields into value object", true), 3);
 
-        pojoConstructorCh = genPnl.add(checkBox("Generate constructors for POJOs",
+        pojoConstructorCh = genPnl.add(Controls.checkBox("Generate constructors for POJOs",
             "If selected then generate empty and full constructors for POJOs", false), 3);
 
-        xmlSingleFileCh = genPnl.add(checkBox("Write all configurations to a single XML file",
+        xmlSingleFileCh = genPnl.add(Controls.checkBox("Write all configurations to a single XML file",
             "If selected then all configurations will be saved into the file 'ignite-type-metadata.xml'", true), 3);
 
-        GridPaneEx regexPnl = paneEx(5, 5, 5, 5);
+        GridPaneEx regexPnl = Controls.paneEx(5, 5, 5, 5);
         regexPnl.addColumn();
         regexPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
         regexPnl.addColumn();
         regexPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
 
-        regexTf = regexPnl.addLabeled("  Regexp:", textField("Regular expression. For example: (\\w+)"));
+        regexTf = regexPnl.addLabeled("  Regexp:", Controls.textField("Regular expression. For example: (\\w+)"));
 
-        replaceTf = regexPnl.addLabeled("  Replace with:", textField("Replace text. For example: $1_SomeText"));
+        replaceTf = regexPnl.addLabeled("  Replace with:", Controls.textField("Replace text. For example: $1_SomeText"));
 
-        final ComboBox<String> replaceCb = regexPnl.addLabeled("  Replace:", comboBox("Replacement target",
+        final ComboBox<String> replaceCb = regexPnl.addLabeled("  Replace:", Controls.comboBox("Replacement target",
             "Key class names", "Value class names", "Java names"));
 
-        regexPnl.add(buttonsPane(Pos.CENTER_LEFT, false,
-            button("Rename Selected", "Replaces each substring of this string that matches the given regular expression" +
+        regexPnl.add(Controls.buttonsPane(Pos.CENTER_LEFT, false,
+            Controls.button("Rename Selected", "Replaces each substring of this string that matches the given regular expression" +
                     " with the given replacement",
                 new EventHandler<ActionEvent>() {
                     @Override public void handle(ActionEvent evt) {
@@ -1216,7 +1080,7 @@ public class SchemaImportApp extends Application {
                         }
                     }
                 }),
-            button("Reset Selected", "Revert changes for selected items to initial auto-generated values", new EventHandler<ActionEvent>() {
+            Controls.button("Reset Selected", "Revert changes for selected items to initial auto-generated values", new EventHandler<ActionEvent>() {
                 @Override public void handle(ActionEvent evt) {
                     String sel = replaceCb.getSelectionModel().getSelectedItem();
 
@@ -1312,10 +1176,10 @@ public class SchemaImportApp extends Application {
             }
         });
 
-        genPnl.add(titledPane("Rename \"Key class name\", \"Value class name\" or  \"Java name\" for selected tables",
+        genPnl.add(Controls.titledPane("Rename \"Key class name\", \"Value class name\" or  \"Java name\" for selected tables",
             regexPnl, true), 3);
 
-        genLayerPnl = stackPane(genPnl);
+        genLayerPnl = Controls.stackPane(genPnl);
     }
 
     /**
@@ -1548,7 +1412,7 @@ public class SchemaImportApp extends Application {
 
                 if (customPrefsFile == null)
                     log.log(Level.WARNING, "Failed to resolve path to file with custom preferences: " +
-                        customPrefsFile);
+                        customPrefsFileName);
                 else {
                     Properties customPrefs = new Properties();
 
@@ -1577,21 +1441,21 @@ public class SchemaImportApp extends Application {
         primaryStage.setTitle("Apache Ignite Auto Schema Import Utility");
 
         primaryStage.getIcons().addAll(
-            image("ignite", 16),
-            image("ignite", 24),
-            image("ignite", 32),
-            image("ignite", 48),
-            image("ignite", 64),
-            image("ignite", 128));
+            Controls.image("ignite", 16),
+            Controls.image("ignite", 24),
+            Controls.image("ignite", 32),
+            Controls.image("ignite", 48),
+            Controls.image("ignite", 64),
+            Controls.image("ignite", 128));
 
-        pi = progressIndicator(50);
+        pi = Controls.progressIndicator(50);
 
         createGeneratePane();
 
         hdrPane = createHeaderPane();
-        rootPane = borderPane(hdrPane, createConnectionPane(), createButtonsPane(), null, null);
+        rootPane = Controls.borderPane(hdrPane, createConnectionPane(), createButtonsPane(), null, null);
 
-        primaryStage.setScene(scene(rootPane));
+        primaryStage.setScene(Controls.scene(rootPane));
 
         primaryStage.setWidth(650);
         primaryStage.setMinWidth(650);
@@ -1709,37 +1573,49 @@ public class SchemaImportApp extends Application {
         savePreferences();
     }
 
-    /**
-     * Schema Import utility launcher.
-     *
-     * @param args Command line arguments passed to the application.
-     */
-    public static void main(String[] args) {
-        // Workaround for JavaFX ugly text AA.
-        System.setProperty("prism.lcdtext", "false");
-        System.setProperty("prism.text", "t2k");
+    /** Presets for database settings. */
+    private static class Preset {
+        /** Name in preferences. */
+        private String pref;
 
-        // Workaround for AWT + JavaFX: we should initialize AWT before JavaFX.
-        java.awt.Toolkit.getDefaultToolkit();
+        /** RDBMS name to show on screen. */
+        private String name;
 
-        // Workaround for JavaFX + Mac OS dock icon.
-        if (System.getProperty("os.name").toLowerCase().contains("mac os")) {
-            System.setProperty("javafx.macosx.embedded", "true");
+        /** Path to JDBC driver jar. */
+        private String jar;
 
-            try {
-                Class<?> appCls = Class.forName("com.apple.eawt.Application");
+        /** JDBC driver class name. */
+        private String drv;
 
-                Object osxApp = appCls.getDeclaredMethod("getApplication").invoke(null);
+        /** JDBC URL. */
+        private String url;
 
-                appCls.getDeclaredMethod("setDockIconImage", java.awt.Image.class)
-                    .invoke(osxApp, fromFXImage(image("ignite", 128), null));
-            }
-            catch (Exception ignore) {
-                // No-op.
-            }
+        /** User name. */
+        private String user;
+
+        /**
+         * Preset constructor.
+         *
+         * @param pref Name in preferences.
+         * @param name RDBMS name to show on screen.
+         * @param jar Path to JDBC driver jar..
+         * @param drv JDBC driver class name.
+         * @param url JDBC URL.
+         * @param user User name.
+         */
+        Preset(String pref, String name, String jar, String drv, String url, String user) {
+            this.pref = pref;
+            this.name = name;
+            this.jar = jar;
+            this.drv = drv;
+            this.url = url;
+            this.user = user;
         }
 
-        launch(args);
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return name;
+        }
     }
 
     /**
@@ -1750,19 +1626,6 @@ public class SchemaImportApp extends Application {
         private final ComboBox<String> comboBox;
 
         /**
-         * Creates a ComboBox cell factory for use in TableColumn controls.
-         *
-         * @return Cell factory for cell with java types combobox.
-         */
-        public static Callback<TableColumn<PojoField, String>, TableCell<PojoField, String>> cellFactory() {
-            return new Callback<TableColumn<PojoField, String>, TableCell<PojoField, String>>() {
-                @Override public TableCell<PojoField, String> call(TableColumn<PojoField, String> col) {
-                    return new JavaTypeCell();
-                }
-            };
-        }
-
-        /**
          * Default constructor.
          */
         private JavaTypeCell() {
@@ -1778,6 +1641,19 @@ public class SchemaImportApp extends Application {
             getStyleClass().add("combo-box-table-cell");
         }
 
+        /**
+         * Creates a ComboBox cell factory for use in TableColumn controls.
+         *
+         * @return Cell factory for cell with java types combobox.
+         */
+        public static Callback<TableColumn<PojoField, String>, TableCell<PojoField, String>> cellFactory() {
+            return new Callback<TableColumn<PojoField, String>, TableCell<PojoField, String>>() {
+                @Override public TableCell<PojoField, String> call(TableColumn<PojoField, String> col) {
+                    return new JavaTypeCell();
+                }
+            };
+        }
+
         /** {@inheritDoc} */
         @Override public void startEdit() {
             if (comboBox.getItems().size() > 1) {
@@ -1827,8 +1703,8 @@ public class SchemaImportApp extends Application {
      * Special list view cell to select loaded schemas.
      */
     private static class SchemaCell implements Callback<SchemaDescriptor, ObservableValue<Boolean>> {
-        @Override
-        public ObservableValue<Boolean> call(SchemaDescriptor item) {
+        /** {@inheritDoc} */
+        @Override public ObservableValue<Boolean> call(SchemaDescriptor item) {
             return item.selected();
         }
     }
@@ -1837,6 +1713,11 @@ public class SchemaImportApp extends Application {
      * Special table cell to select schema or table.
      */
     private static class PojoDescriptorCell extends TableCell<PojoDescriptor, Boolean> {
+        /** Previous POJO bound to cell. */
+        private PojoDescriptor prevPojo;
+        /** Previous cell graphic. */
+        private Pane prevGraphic;
+
         /**
          * Creates a ComboBox cell factory for use in TableColumn controls.
          *
@@ -1850,12 +1731,6 @@ public class SchemaImportApp extends Application {
             };
         }
 
-        /** Previous POJO bound to cell. */
-        private PojoDescriptor prevPojo;
-
-        /** Previous cell graphic. */
-        private Pane prevGraphic;
-
         /** {@inheritDoc} */
         @Override public void updateItem(Boolean item, boolean empty) {
             super.updateItem(item, empty);
@@ -1898,6 +1773,11 @@ public class SchemaImportApp extends Application {
      * Special table cell to select &quot;used&quot; fields for code generation.
      */
     private static class PojoFieldUseCell extends TableCell<PojoField, Boolean> {
+        /** Previous POJO field bound to cell. */
+        private PojoField prevField;
+        /** Previous cell graphic. */
+        private CheckBox prevGraphic;
+
         /**
          * Creates a ComboBox cell factory for use in TableColumn controls.
          *
@@ -1911,12 +1791,6 @@ public class SchemaImportApp extends Application {
             };
         }
 
-        /** Previous POJO field bound to cell. */
-        private PojoField prevField;
-
-        /** Previous cell graphic. */
-        private CheckBox prevGraphic;
-
         /** {@inheritDoc} */
         @Override public void updateItem(Boolean item, boolean empty) {
             super.updateItem(item, empty);
@@ -1947,4 +1821,4 @@ public class SchemaImportApp extends Application {
             }
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd50bdf8/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index ba44c85..5a1d385 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -21,8 +21,8 @@
     POM file.
 -->
 <project
-        xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
@@ -708,6 +708,7 @@
                                         <exclude>dev-tools/.gradle/**/*</exclude>
                                         <exclude>dev-tools/gradle/wrapper/**/*</exclude>
                                         <exclude>dev-tools/gradlew</exclude>
+                                        <exclude>src/main/js/package.json</exclude>
                                         <!--shmem-->
                                         <exclude>ipc/shmem/**/Makefile.in</exclude><!--auto generated files-->
                                         <exclude>ipc/shmem/**/Makefile</exclude><!--auto generated files-->

http://git-wip-us.apache.org/repos/asf/ignite/blob/bd50bdf8/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 208dbbc..a2e61cd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@
 <!--
     POM file.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
@@ -660,6 +660,7 @@
             </activation>
             <modules>
                 <module>modules/schema-import</module>
+                <module>modules/schema-import-db</module>
             </modules>
             <build>
                 <plugins>
@@ -716,6 +717,7 @@
             </activation>
             <modules>
                 <module>modules/schema-import</module>
+                <module>modules/schema-import-db</module>
             </modules>
             <build>
                 <plugins>
@@ -764,6 +766,42 @@
         </profile>
 
         <profile>
+            <id>control-center</id>
+            <modules>
+                <module>modules/control-center-agent</module>
+                <module>modules/control-center-web</module>
+                <module>modules/schema-import-db</module>
+            </modules>
+        </profile>
+
+        <profile>
+            <id>ignite-npm</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>compile</phase>
+                                <goals>
+                                    <goal>exec</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                        <configuration>
+                            <executable>npm</executable>
+                            <arguments>
+                                <argument>publish</argument>
+                                <argument>modules/nodejs/src/main/js</argument>
+                            </arguments>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        
+        <profile>
             <id>update-versions</id>
             <!-- updates dotnet & cpp versions -->
             <build>