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 2016/01/15 12:04:03 UTC

[2/6] ignite git commit: IGNITE-843 WIP

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/Employee.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/Employee.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/Employee.java
deleted file mode 100644
index 9238845..0000000
--- a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/Employee.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.agent.demo.model;
-
-import java.io.Serializable;
-
-/**
- * Employee definition.
- *
- * Code generated by Apache Ignite Schema Import utility: 08/24/2015.
- */
-public class Employee implements Serializable {
-    /** */
-    private static final long serialVersionUID = 0L;
-
-    /** Value for employeeId. */
-    private int employeeId;
-
-    /** Value for firstName. */
-    private String firstName;
-
-    /** Value for lastName. */
-    private String lastName;
-
-    /** Value for email. */
-    private String email;
-
-    /** Value for phoneNumber. */
-    private String phoneNumber;
-
-    /** Value for hireDate. */
-    private java.sql.Date hireDate;
-
-    /** Value for job. */
-    private String job;
-
-    /** Value for salary. */
-    private Double salary;
-
-    /** Value for managerId. */
-    private Integer managerId;
-
-    /** Value for departmentId. */
-    private Integer departmentId;
-
-    /**
-     * Empty constructor.
-     */
-    public Employee() {
-        // No-op.
-    }
-
-    /**
-     * Full constructor.
-     */
-    public Employee(
-        int employeeId,
-        String firstName,
-        String lastName,
-        String email,
-        String phoneNumber,
-        java.sql.Date hireDate,
-        String job,
-        Double salary,
-        Integer managerId,
-        Integer departmentId
-    ) {
-        this.employeeId = employeeId;
-        this.firstName = firstName;
-        this.lastName = lastName;
-        this.email = email;
-        this.phoneNumber = phoneNumber;
-        this.hireDate = hireDate;
-        this.job = job;
-        this.salary = salary;
-        this.managerId = managerId;
-        this.departmentId = departmentId;
-    }
-
-    /**
-     * Gets employeeId.
-     *
-     * @return Value for employeeId.
-     */
-    public int getEmployeeId() {
-        return employeeId;
-    }
-
-    /**
-     * Sets employeeId.
-     *
-     * @param employeeId New value for employeeId.
-     */
-    public void setEmployeeId(int employeeId) {
-        this.employeeId = employeeId;
-    }
-
-    /**
-     * Gets firstName.
-     *
-     * @return Value for firstName.
-     */
-    public String getFirstName() {
-        return firstName;
-    }
-
-    /**
-     * Sets firstName.
-     *
-     * @param firstName New value for firstName.
-     */
-    public void setFirstName(String firstName) {
-        this.firstName = firstName;
-    }
-
-    /**
-     * Gets lastName.
-     *
-     * @return Value for lastName.
-     */
-    public String getLastName() {
-        return lastName;
-    }
-
-    /**
-     * Sets lastName.
-     *
-     * @param lastName New value for lastName.
-     */
-    public void setLastName(String lastName) {
-        this.lastName = lastName;
-    }
-
-    /**
-     * Gets email.
-     *
-     * @return Value for email.
-     */
-    public String getEmail() {
-        return email;
-    }
-
-    /**
-     * Sets email.
-     *
-     * @param email New value for email.
-     */
-    public void setEmail(String email) {
-        this.email = email;
-    }
-
-    /**
-     * Gets phoneNumber.
-     *
-     * @return Value for phoneNumber.
-     */
-    public String getPhoneNumber() {
-        return phoneNumber;
-    }
-
-    /**
-     * Sets phoneNumber.
-     *
-     * @param phoneNumber New value for phoneNumber.
-     */
-    public void setPhoneNumber(String phoneNumber) {
-        this.phoneNumber = phoneNumber;
-    }
-
-    /**
-     * Gets hireDate.
-     *
-     * @return Value for hireDate.
-     */
-    public java.sql.Date getHireDate() {
-        return hireDate;
-    }
-
-    /**
-     * Sets hireDate.
-     *
-     * @param hireDate New value for hireDate.
-     */
-    public void setHireDate(java.sql.Date hireDate) {
-        this.hireDate = hireDate;
-    }
-
-    /**
-     * Gets job.
-     *
-     * @return Value for job.
-     */
-    public String getJob() {
-        return job;
-    }
-
-    /**
-     * Sets job.
-     *
-     * @param job New value for job.
-     */
-    public void setJob(String job) {
-        this.job = job;
-    }
-
-    /**
-     * Gets salary.
-     *
-     * @return Value for salary.
-     */
-    public Double getSalary() {
-        return salary;
-    }
-
-    /**
-     * Sets salary.
-     *
-     * @param salary New value for salary.
-     */
-    public void setSalary(Double salary) {
-        this.salary = salary;
-    }
-
-    /**
-     * Gets managerId.
-     *
-     * @return Value for managerId.
-     */
-    public Integer getManagerId() {
-        return managerId;
-    }
-
-    /**
-     * Sets managerId.
-     *
-     * @param managerId New value for managerId.
-     */
-    public void setManagerId(Integer managerId) {
-        this.managerId = managerId;
-    }
-
-    /**
-     * Gets departmentId.
-     *
-     * @return Value for departmentId.
-     */
-    public Integer getDepartmentId() {
-        return departmentId;
-    }
-
-    /**
-     * Sets departmentId.
-     *
-     * @param departmentId New value for departmentId.
-     */
-    public void setDepartmentId(Integer departmentId) {
-        this.departmentId = departmentId;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean equals(Object o) {
-        if (this == o)
-            return true;
-
-        if (!(o instanceof Employee))
-            return false;
-
-        Employee that = (Employee)o;
-
-        if (employeeId != that.employeeId)
-            return false;
-
-        if (firstName != null ? !firstName.equals(that.firstName) : that.firstName != null)
-            return false;
-
-        if (lastName != null ? !lastName.equals(that.lastName) : that.lastName != null)
-            return false;
-
-        if (email != null ? !email.equals(that.email) : that.email != null)
-            return false;
-
-        if (phoneNumber != null ? !phoneNumber.equals(that.phoneNumber) : that.phoneNumber != null)
-            return false;
-
-        if (hireDate != null ? !hireDate.equals(that.hireDate) : that.hireDate != null)
-            return false;
-
-        if (job != null ? !job.equals(that.job) : that.job != null)
-            return false;
-
-        if (salary != null ? !salary.equals(that.salary) : that.salary != null)
-            return false;
-
-        if (managerId != null ? !managerId.equals(that.managerId) : that.managerId != null)
-            return false;
-
-        if (departmentId != null ? !departmentId.equals(that.departmentId) : that.departmentId != null)
-            return false;
-
-        return true;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int hashCode() {
-        int res = employeeId;
-
-        res = 31 * res + (firstName != null ? firstName.hashCode() : 0);
-
-        res = 31 * res + (lastName != null ? lastName.hashCode() : 0);
-
-        res = 31 * res + (email != null ? email.hashCode() : 0);
-
-        res = 31 * res + (phoneNumber != null ? phoneNumber.hashCode() : 0);
-
-        res = 31 * res + (hireDate != null ? hireDate.hashCode() : 0);
-
-        res = 31 * res + (job != null ? job.hashCode() : 0);
-
-        res = 31 * res + (salary != null ? salary.hashCode() : 0);
-
-        res = 31 * res + (managerId != null ? managerId.hashCode() : 0);
-
-        res = 31 * res + (departmentId != null ? departmentId.hashCode() : 0);
-
-        return res;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return "Employee [employeeId=" + employeeId +
-            ", firstName=" + firstName +
-            ", lastName=" + lastName +
-            ", email=" + email +
-            ", phoneNumber=" + phoneNumber +
-            ", hireDate=" + hireDate +
-            ", job=" + job +
-            ", salary=" + salary +
-            ", managerId=" + managerId +
-            ", departmentId=" + departmentId +
-            "]";
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/EmployeeKey.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/EmployeeKey.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/EmployeeKey.java
deleted file mode 100644
index 6a9f4c0..0000000
--- a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/EmployeeKey.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.agent.demo.model;
-
-import java.io.Serializable;
-
-/**
- * EmployeeKey definition.
- *
- * Code generated by Apache Ignite Schema Import utility: 08/24/2015.
- */
-public class EmployeeKey implements Serializable {
-    /** */
-    private static final long serialVersionUID = 0L;
-
-    /** Value for employeeId. */
-    private int employeeId;
-
-    /**
-     * Empty constructor.
-     */
-    public EmployeeKey() {
-        // No-op.
-    }
-
-    /**
-     * Full constructor.
-     */
-    public EmployeeKey(
-        int employeeId
-    ) {
-        this.employeeId = employeeId;
-    }
-
-    /**
-     * Gets employeeId.
-     *
-     * @return Value for employeeId.
-     */
-    public int getEmployeeId() {
-        return employeeId;
-    }
-
-    /**
-     * Sets employeeId.
-     *
-     * @param employeeId New value for employeeId.
-     */
-    public void setEmployeeId(int employeeId) {
-        this.employeeId = employeeId;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean equals(Object o) {
-        if (this == o)
-            return true;
-
-        if (!(o instanceof EmployeeKey))
-            return false;
-
-        EmployeeKey that = (EmployeeKey)o;
-
-        if (employeeId != that.employeeId)
-            return false;
-
-        return true;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int hashCode() {
-        int res = employeeId;
-
-        return res;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return "EmployeeKey [employeeId=" + employeeId +
-            "]";
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/Parking.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/Parking.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/Parking.java
deleted file mode 100644
index 7613760..0000000
--- a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/Parking.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.agent.demo.model;
-
-import java.io.Serializable;
-
-/**
- * Parking definition.
- *
- * Code generated by Apache Ignite Schema Import utility: 08/24/2015.
- */
-public class Parking implements Serializable {
-    /** */
-    private static final long serialVersionUID = 0L;
-
-    /** Value for parkingId. */
-    private int parkingId;
-
-    /** Value for parkingName. */
-    private String parkingName;
-
-    /**
-     * Empty constructor.
-     */
-    public Parking() {
-        // No-op.
-    }
-
-    /**
-     * Full constructor.
-     */
-    public Parking(
-        int parkingId,
-        String parkingName
-    ) {
-        this.parkingId = parkingId;
-        this.parkingName = parkingName;
-    }
-
-    /**
-     * Gets parkingId.
-     *
-     * @return Value for parkingId.
-     */
-    public int getParkingId() {
-        return parkingId;
-    }
-
-    /**
-     * Sets parkingId.
-     *
-     * @param parkingId New value for parkingId.
-     */
-    public void setParkingId(int parkingId) {
-        this.parkingId = parkingId;
-    }
-
-    /**
-     * Gets parkingName.
-     *
-     * @return Value for parkingName.
-     */
-    public String getParkingName() {
-        return parkingName;
-    }
-
-    /**
-     * Sets parkingName.
-     *
-     * @param parkingName New value for parkingName.
-     */
-    public void setParkingName(String parkingName) {
-        this.parkingName = parkingName;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean equals(Object o) {
-        if (this == o)
-            return true;
-
-        if (!(o instanceof Parking))
-            return false;
-
-        Parking that = (Parking)o;
-
-        if (parkingId != that.parkingId)
-            return false;
-
-        if (parkingName != null ? !parkingName.equals(that.parkingName) : that.parkingName != null)
-            return false;
-
-        return true;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int hashCode() {
-        int res = parkingId;
-
-        res = 31 * res + (parkingName != null ? parkingName.hashCode() : 0);
-
-        return res;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return "Parking [parkingId=" + parkingId +
-            ", parkingName=" + parkingName +
-            "]";
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/ParkingKey.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/ParkingKey.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/ParkingKey.java
deleted file mode 100644
index a68e8e5..0000000
--- a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/demo/model/ParkingKey.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.agent.demo.model;
-
-import java.io.Serializable;
-
-/**
- * ParkingKey definition.
- *
- * Code generated by Apache Ignite Schema Import utility: 08/24/2015.
- */
-public class ParkingKey implements Serializable {
-    /** */
-    private static final long serialVersionUID = 0L;
-
-    /** Value for parkingId. */
-    private int parkingId;
-
-    /**
-     * Empty constructor.
-     */
-    public ParkingKey() {
-        // No-op.
-    }
-
-    /**
-     * Full constructor.
-     */
-    public ParkingKey(
-        int parkingId
-    ) {
-        this.parkingId = parkingId;
-    }
-
-    /**
-     * Gets parkingId.
-     *
-     * @return Value for parkingId.
-     */
-    public int getParkingId() {
-        return parkingId;
-    }
-
-    /**
-     * Sets parkingId.
-     *
-     * @param parkingId New value for parkingId.
-     */
-    public void setParkingId(int parkingId) {
-        this.parkingId = parkingId;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean equals(Object o) {
-        if (this == o)
-            return true;
-
-        if (!(o instanceof ParkingKey))
-            return false;
-
-        ParkingKey that = (ParkingKey)o;
-
-        if (parkingId != that.parkingId)
-            return false;
-
-        return true;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int hashCode() {
-        int res = parkingId;
-
-        return res;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return "ParkingKey [parkingId=" + parkingId +
-            "]";
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/agent/handlers/DatabaseMetadataExtractor.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/handlers/DatabaseMetadataExtractor.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/handlers/DatabaseMetadataExtractor.java
deleted file mode 100644
index 0498656..0000000
--- a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/handlers/DatabaseMetadataExtractor.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.agent.handlers;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Properties;
-import org.apache.ignite.agent.AgentConfiguration;
-import org.apache.ignite.agent.remote.Remote;
-import org.apache.ignite.agent.demo.AgentMetadataDemo;
-import org.apache.ignite.schema.parser.DbMetadataReader;
-import org.apache.ignite.schema.parser.DbTable;
-import org.apache.log4j.Logger;
-
-import static org.apache.ignite.agent.AgentUtils.resolvePath;
-
-/**
- * Remote API to extract database metadata.
- */
-public class DatabaseMetadataExtractor {
-    /** */
-    private static final Logger log = Logger.getLogger(DatabaseMetadataExtractor.class.getName());
-
-    /** */
-    private final File driversFolder;
-
-    /**
-     * @param cfg Config.
-     */
-    public DatabaseMetadataExtractor(AgentConfiguration cfg) {
-        driversFolder = resolvePath(cfg.driversFolder() == null ? "jdbc-drivers" : cfg.driversFolder());
-    }
-
-    /**
-     * @param jdbcDriverJarPath JDBC driver JAR path.
-     * @param jdbcDriverCls JDBC driver class.
-     * @param jdbcUrl JDBC URL.
-     * @param jdbcInfo Properties to connect to database.
-     * @return Connection to database.
-     * @throws SQLException
-     */
-    private Connection connect(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl, Properties jdbcInfo) throws SQLException {
-        if (!new File(jdbcDriverJarPath).isAbsolute() && driversFolder != null)
-            jdbcDriverJarPath = new File(driversFolder, jdbcDriverJarPath).getPath();
-
-        if (AgentMetadataDemo.isTestDriveUrl(jdbcUrl))
-            AgentMetadataDemo.testDrive();
-
-        return DbMetadataReader.getInstance().connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo);
-    }
-
-    /**
-     * @param jdbcDriverJarPath JDBC driver JAR path.
-     * @param jdbcDriverCls JDBC driver class.
-     * @param jdbcUrl JDBC URL.
-     * @param jdbcInfo Properties to connect to database.
-     * @return Collection of schema names.
-     * @throws SQLException
-     */
-    @Remote
-    public Collection<String> schemas(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
-        Properties jdbcInfo) throws SQLException {
-        log.debug("Start collecting database schemas [driver jar=" + jdbcDriverJarPath +
-            ", driver class=" + jdbcDriverCls + ", url=" + jdbcUrl + "]");
-
-        try (Connection conn = connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo)) {
-            Collection<String> schemas = DbMetadataReader.getInstance().schemas(conn);
-
-            log.debug("Finished collection of schemas [url=" + jdbcUrl + ", count="+ schemas.size() +"]");
-
-            return schemas;
-        }
-        catch (Throwable e) {
-            log.error("Failed to collect schemas", e);
-
-            throw new SQLException("Failed to collect schemas", e);
-        }
-    }
-
-    /**
-     * @param jdbcDriverJarPath JDBC driver JAR path.
-     * @param jdbcDriverCls JDBC driver class.
-     * @param jdbcUrl JDBC URL.
-     * @param jdbcInfo Properties to connect to database.
-     * @param schemas List of schema names to process.
-     * @param tblsOnly If {@code true} then only tables will be processed otherwise views also will be processed.
-     * @return Collection of tables.
-     */
-    @Remote
-    public Collection<DbTable> metadata(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
-        Properties jdbcInfo, List<String> schemas, boolean tblsOnly) throws SQLException {
-        log.debug("Start collecting database metadata [driver jar=" + jdbcDriverJarPath +
-            ", driver class=" + jdbcDriverCls + ", url=" + jdbcUrl + "]");
-
-        try (Connection conn = connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo)) {
-            Collection<DbTable> metadata = DbMetadataReader.getInstance().metadata(conn, schemas, tblsOnly);
-
-            log.debug("Finished collection of metadata [url=" + jdbcUrl + ", count="+ metadata.size() +"]");
-
-            return metadata;
-        }
-        catch (Throwable e) {
-            log.error("Failed to collect metadata", e);
-
-            throw new SQLException("Failed to collect metadata", e);
-        }
-    }
-
-    /**
-     * @return Drivers in drivers folder
-     * @see AgentConfiguration#driversFolder
-     */
-    @Remote
-    public List<JdbcDriver> availableDrivers() {
-        if (driversFolder == null) {
-            log.info("JDBC drivers folder not specified, returning empty list");
-
-            return Collections.emptyList();
-        }
-
-        log.debug("Collecting JDBC drivers in folder: " + driversFolder.getPath());
-
-        File[] list = driversFolder.listFiles(new FilenameFilter() {
-            @Override public boolean accept(File dir, String name) {
-                return name.endsWith(".jar");
-            }
-        });
-
-        if (list == null) {
-            log.info("JDBC drivers folder has no files, returning empty list");
-
-            return Collections.emptyList();
-        }
-
-        List<JdbcDriver> res = new ArrayList<>();
-
-        for (File file : list) {
-            try {
-                boolean win = System.getProperty("os.name").contains("win");
-
-                URL url = new URL("jar", null, "file:" + (win ? "/" : "") + file.getPath() + "!/META-INF/services/java.sql.Driver");
-
-                try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
-                    String jdbcDriverCls = reader.readLine();
-
-                    res.add(new JdbcDriver(file.getName(), jdbcDriverCls));
-
-                    log.debug("Found: [driver=" + file + ", class=" + jdbcDriverCls + "]");
-                }
-            }
-            catch (IOException e) {
-                res.add(new JdbcDriver(file.getName(), null));
-
-                log.info("Found: [driver=" + file + "]");
-                log.info("Failed to detect driver class: " + e.getMessage());
-            }
-        }
-
-        return res;
-    }
-
-    /**
-     * Wrapper class for later to be transformed to JSON and send to Web Console.
-     */
-    private static class JdbcDriver {
-        /** */
-        private final String jdbcDriverJar;
-        /** */
-        private final String jdbcDriverClass;
-
-        /**
-         * @param jdbcDriverJar File name of driver jar file.
-         * @param jdbcDriverClass Optional JDBC driver class.
-         */
-        public JdbcDriver(String jdbcDriverJar, String jdbcDriverClass) {
-            this.jdbcDriverJar = jdbcDriverJar;
-            this.jdbcDriverClass = jdbcDriverClass;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/agent/handlers/RestExecutor.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/handlers/RestExecutor.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/handlers/RestExecutor.java
deleted file mode 100644
index 99b5626..0000000
--- a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/handlers/RestExecutor.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.agent.handlers;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.ConnectException;
-import java.net.URISyntaxException;
-import java.nio.charset.Charset;
-import java.util.List;
-import java.util.Map;
-import org.apache.commons.codec.Charsets;
-import org.apache.http.Header;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpRequestBase;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.ignite.agent.AgentConfiguration;
-import org.apache.ignite.agent.remote.Remote;
-import org.apache.ignite.agent.demo.AgentSqlDemo;
-import org.apache.log4j.Logger;
-
-import static org.apache.ignite.agent.AgentConfiguration.DFLT_NODE_PORT;
-
-/**
- * Executor for REST requests.
- */
-public class RestExecutor {
-    /** */
-    private static final Logger log = Logger.getLogger(RestExecutor.class.getName());
-
-    /** */
-    private final AgentConfiguration cfg;
-
-    /** */
-    private CloseableHttpClient httpClient;
-
-    /**
-     * @param cfg Config.
-     */
-    public RestExecutor(AgentConfiguration cfg) {
-        this.cfg = cfg;
-    }
-
-    /**
-     *
-     */
-    public void start() {
-        httpClient = HttpClientBuilder.create().build();
-    }
-
-    /**
-     *
-     */
-    public void stop() throws IOException {
-        if (httpClient != null)
-            httpClient.close();
-    }
-
-    /**
-     * @param path Path.
-     * @param mtd Method.
-     * @param params Params.
-     * @param headers Headers.
-     * @param body Body.
-     */
-    @Remote
-    public RestResult executeRest(String path, Map<String, String> params, String mtd, Map<String, String> headers,
-        String body) throws IOException, URISyntaxException {
-        log.debug("Start execute REST command [url=/" + path + ", method=" + mtd +
-            ", parameters=" + params + "]");
-
-        URIBuilder builder = new URIBuilder(cfg.nodeUri());
-
-        if (builder.getPort() == -1)
-            builder.setPort(DFLT_NODE_PORT);
-
-        if (path != null) {
-            if (!path.startsWith("/") && !cfg.nodeUri().endsWith("/"))
-                path = '/' + path;
-
-            builder.setPath(path);
-        }
-
-        if (params != null) {
-            for (Map.Entry<String, String> entry : params.entrySet())
-                builder.addParameter(entry.getKey(), entry.getValue());
-        }
-
-        HttpRequestBase httpReq;
-
-        if ("GET".equalsIgnoreCase(mtd))
-            httpReq = new HttpGet(builder.build());
-        else if ("POST".equalsIgnoreCase(mtd)) {
-            HttpPost post;
-
-            if (body == null) {
-                List<NameValuePair> nvps = builder.getQueryParams();
-
-                builder.clearParameters();
-
-                post = new HttpPost(builder.build());
-
-                if (!nvps.isEmpty())
-                    post.setEntity(new UrlEncodedFormEntity(nvps));
-            }
-            else {
-                post = new HttpPost(builder.build());
-
-                post.setEntity(new StringEntity(body));
-            }
-
-            httpReq = post;
-        }
-        else
-            throw new IOException("Unknown HTTP-method: " + mtd);
-
-        if (headers != null) {
-            for (Map.Entry<String, String> entry : headers.entrySet())
-                httpReq.addHeader(entry.getKey(), entry.getValue());
-        }
-
-        try (CloseableHttpResponse resp = httpClient.execute(httpReq)) {
-            ByteArrayOutputStream out = new ByteArrayOutputStream();
-
-            resp.getEntity().writeTo(out);
-
-            Charset charset = Charsets.UTF_8;
-
-            Header encodingHdr = resp.getEntity().getContentEncoding();
-
-            if (encodingHdr != null) {
-                String encoding = encodingHdr.getValue();
-
-                charset = Charsets.toCharset(encoding);
-            }
-
-            return new RestResult(resp.getStatusLine().getStatusCode(), new String(out.toByteArray(), charset));
-        }
-        catch (ConnectException e) {
-            log.debug("Failed connect to node and execute REST command [uri=" + builder.build() + "]");
-
-            return new RestResult(404, "Failed connect to node and execute REST command.");
-        }
-    }
-
-    /**
-     * Enable test-drive SQL.
-     */
-    @Remote
-    public boolean startDemoSQL() {
-        return AgentSqlDemo.testDrive(cfg);
-    }
-
-    /**
-     * Request result.
-     */
-    public static class RestResult {
-        /** Status code. */
-        private int code;
-
-        /** Message. */
-        private String message;
-
-        /**
-         * @param code Code.
-         * @param msg Message.
-         */
-        public RestResult(int code, String msg) {
-            this.code = code;
-            message = msg;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/Remote.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/Remote.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/Remote.java
deleted file mode 100644
index 8fe49bd..0000000
--- a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/Remote.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.agent.remote;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Use this annotation to associate methods with remote NodeJS server commands.
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Remote {
-    /**
-     * Whether or not method should be executed synchronously.
-     *
-     * @return {@code true} if method will be executed in separated thread otherwise if method will be executed in handler thread.
-     */
-    boolean async() default true;
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/RemoteHandler.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/RemoteHandler.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/RemoteHandler.java
deleted file mode 100644
index e15280f..0000000
--- a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/RemoteHandler.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.agent.remote;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonNull;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import org.apache.http.auth.AuthenticationException;
-import org.apache.log4j.Logger;
-
-/**
- * Allow to execute methods remotely from NodeJS server by web-socket command.
- */
-public class RemoteHandler implements AutoCloseable {
-    /** */
-    public static final Gson GSON = new Gson();
-
-    /** */
-    public static final Object[] EMPTY_OBJECTS = new Object[0];
-
-    /** */
-    private static final Logger log = Logger.getLogger(RemoteHandler.class.getName());
-
-    /** */
-    private static final String INTERNAL_EXCEPTION_TYPE = "org.apache.ignite.agent.AgentException";
-
-    /** */
-    private final WebSocketSender snd;
-
-    /** */
-    private final Map<String, MethodDescriptor> mtds = new HashMap<>();
-
-    /** */
-    private final ExecutorService executorSrvc = Executors.newFixedThreadPool(Runtime.getRuntime()
-        .availableProcessors());
-
-    /**
-     * @param snd Session.
-     * @param hnds Handlers.
-     */
-    private RemoteHandler(WebSocketSender snd, Object ... hnds) {
-        this.snd = snd;
-
-        for (Object hnd : hnds) {
-            for (Method method : hnd.getClass().getMethods()) {
-                Remote remoteAnn = method.getAnnotation(Remote.class);
-
-                if (remoteAnn != null) {
-                    MethodDescriptor old = mtds.put(method.getName(), new MethodDescriptor(method, hnd,
-                        remoteAnn.async()));
-
-                    if (old != null)
-                        throw new IllegalArgumentException("Duplicated method: " + method.getName());
-                }
-            }
-        }
-    }
-
-    /**
-     * @param hnds Handler.
-     * @param snd Sender.
-     */
-    public static RemoteHandler wrap(WebSocketSender snd, Object ... hnds) {
-        return new RemoteHandler(snd, hnds);
-    }
-
-    /**
-     * @param req Request.
-     */
-    public void onMessage(JsonObject req) {
-        JsonPrimitive reqIdJson = req.getAsJsonPrimitive("reqId");
-
-        final Long reqId = reqIdJson == null ? null : reqIdJson.getAsLong();
-
-        String mtdName = req.getAsJsonPrimitive("mtdName").getAsString();
-
-        final MethodDescriptor desc = mtds.get(mtdName);
-
-        if (desc == null) {
-            sendException(reqId, INTERNAL_EXCEPTION_TYPE, "Unknown method: " + mtdName);
-
-            return;
-        }
-
-        Type[] paramTypes = desc.mtd.getGenericParameterTypes();
-
-        JsonArray argsJson = req.getAsJsonArray("args");
-
-        final Object[] args;
-
-        if (paramTypes.length > 0) {
-            args = new Object[paramTypes.length];
-
-            if (argsJson == null || argsJson.size() != paramTypes.length) {
-                sendException(reqId, INTERNAL_EXCEPTION_TYPE, "Inconsistent parameters");
-
-                return;
-            }
-
-            for (int i = 0; i < paramTypes.length; i++)
-                args[i] = GSON.fromJson(argsJson.get(i), paramTypes[i]);
-        }
-        else {
-            args = EMPTY_OBJECTS;
-
-            if (argsJson != null && argsJson.size() > 0) {
-                sendException(reqId, INTERNAL_EXCEPTION_TYPE, "Inconsistent parameters");
-
-                return;
-            }
-        }
-
-        Runnable run = new Runnable() {
-            @Override public void run() {
-                final Object res;
-
-                try {
-                    res = desc.mtd.invoke(desc.hnd, args);
-                }
-                catch (Throwable e) {
-                    if (e instanceof AuthenticationException) {
-                        close();
-
-                        return;
-                    }
-
-                    if (e instanceof InvocationTargetException)
-                        e = ((InvocationTargetException)e).getTargetException();
-
-                    if (reqId != null)
-                        sendException(reqId, e.getClass().getName(), e.getMessage());
-                    else
-                        log.error("Exception on execute remote method.", e);
-
-                    return;
-                }
-
-                sendResponse(reqId, res, desc.returnType);
-            }
-        };
-
-        if (desc.async)
-            executorSrvc.submit(run);
-        else
-            run.run();
-    }
-
-    /**
-     * @param reqId Request id.
-     * @param exType Exception class name.
-     * @param exMsg Exception message.
-     */
-    protected void sendException(Long reqId, String exType, String exMsg) {
-        if (reqId == null)
-            return;
-
-        JsonObject res = new JsonObject();
-
-        res.addProperty("type", "CallRes");
-        res.addProperty("reqId", reqId);
-
-        JsonObject exJson = new JsonObject();
-        exJson.addProperty("type", exType);
-        exJson.addProperty("message", exMsg);
-
-        res.add("ex", exJson);
-
-        snd.send(res);
-    }
-
-    /**
-     * @param reqId Request id.
-     * @param res Result.
-     * @param type Type.
-     */
-    private void sendResponse(Long reqId, Object res, Type type) {
-        if (reqId == null)
-            return;
-
-        JsonObject resp = new JsonObject();
-
-        resp.addProperty("type", "CallRes");
-
-        resp.addProperty("reqId", reqId);
-
-        JsonElement resJson = type == void.class ? JsonNull.INSTANCE : GSON.toJsonTree(res, type);
-
-        resp.add("res", resJson);
-
-        snd.send(resp);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void close() {
-        executorSrvc.shutdown();
-    }
-
-    /**
-     *
-     */
-    private static class MethodDescriptor {
-        /** */
-        private final Method mtd;
-
-        /** */
-        private final Object hnd;
-
-        /** */
-        private final Type returnType;
-
-        /** */
-        private final boolean async;
-
-        /**
-         * @param mtd Method.
-         * @param hnd Handler.
-         * @param async Async.
-         */
-        MethodDescriptor(Method mtd, Object hnd, boolean async) {
-            this.mtd = mtd;
-            this.hnd = hnd;
-            this.async = async;
-
-            returnType = mtd.getGenericReturnType();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/WebSocketSender.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/WebSocketSender.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/WebSocketSender.java
deleted file mode 100644
index 655ff85..0000000
--- a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/remote/WebSocketSender.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.agent.remote;
-
-import com.google.gson.JsonObject;
-
-/**
- * Sender for messages to web-socket.
- */
-public interface WebSocketSender {
-    /**
-     * Send message.
-     * @param msg Message.
-     * @return {@code true} if message sent successfully.
-     */
-    public boolean send(String msg);
-
-    /**
-     * Send message.
-     * @param msg Message.
-     * @return {@code true} if message sent successfully.
-     */
-    public boolean send(JsonObject msg);
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentConfiguration.java b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentConfiguration.java
new file mode 100644
index 0000000..6259cca
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentConfiguration.java
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.console.agent;
+
+import com.beust.jcommander.Parameter;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.Properties;
+
+/**
+ * Agent configuration.
+ */
+public class AgentConfiguration {
+    /** Default server port. */
+    public static final int DFLT_SERVER_PORT = 3001;
+
+    /** Default Ignite node HTTP port. */
+    public static final int DFLT_NODE_PORT = 8080;
+
+    /** Default path to agent property file. */
+    public static final String DFLT_CFG_PATH = "default.properties";
+
+    /** Default server URI. */
+    private static final String DFLT_SERVER_URI = "wss://localhost:3001";
+
+    /** Default Ignite node HTTP URI. */
+    private static final String DFLT_NODE_URI = "http://localhost:8080";
+
+    /** */
+    @Parameter(names = {"-t", "--token"}, description = "User's security token used to establish connection to Ignite Console.")
+    private String tok;
+
+    /** */
+    @Parameter(names = {"-s", "--server-uri"}, description = "URI for connect to Ignite Console via web-socket protocol" +
+        "           " +
+        "      Default value: " + DFLT_SERVER_URI)
+    private String srvUri;
+
+    /** */
+    @Parameter(names = {"-n", "--node-uri"}, description = "URI for connect to Ignite node REST server" +
+        "                        " +
+        "      Default value: " + DFLT_NODE_URI)
+    private String nodeUri;
+
+    /** URI for connect to Ignite demo node REST server */
+    private String demoNodeUri;
+
+    /** */
+    @Parameter(names = {"-c", "--config"}, description = "Path to agent property file" +
+        "                                  " +
+        "      Default value: " + DFLT_CFG_PATH)
+    private String cfgPath;
+
+    /** */
+    @Parameter(names = {"-d", "--driver-folder"}, description = "Path to folder with JDBC drivers" +
+        "                             " +
+        "      Default value: ./jdbc-drivers")
+    private String driversFolder;
+
+    /** */
+    @Parameter(names = { "-h", "--help" }, help = true, description = "Print this help message")
+    private Boolean help;
+
+    /**
+     * @return Token.
+     */
+    public String token() {
+        return tok;
+    }
+
+    /**
+     * @param tok Token.
+     */
+    public void token(String tok) {
+        this.tok = tok;
+    }
+
+    /**
+     * @return Server URI.
+     */
+    public String serverUri() {
+        return srvUri;
+    }
+
+    /**
+     * @param srvUri URI.
+     */
+    public void serverUri(String srvUri) {
+        this.srvUri = srvUri;
+    }
+
+    /**
+     * @return Node URI.
+     */
+    public String nodeUri() {
+        return nodeUri;
+    }
+
+    /**
+     * @param nodeUri Node URI.
+     */
+    public void nodeUri(String nodeUri) {
+        this.nodeUri = nodeUri;
+    }
+
+    /**
+     * @return Demo node URI.
+     */
+    public String demoNodeUri() {
+        return demoNodeUri;
+    }
+
+    /**
+     * @param demoNodeUri Demo node URI.
+     */
+    public void demoNodeUri(String demoNodeUri) {
+        this.demoNodeUri = demoNodeUri;
+    }
+
+    /**
+     * @return Configuration path.
+     */
+    public String configPath() {
+        return cfgPath == null ? DFLT_CFG_PATH : cfgPath;
+    }
+
+    /**
+     * @return Configured drivers folder.
+     */
+    public String driversFolder() {
+        return driversFolder;
+    }
+
+    /**
+     * @param driversFolder Driver folder.
+     */
+    public void driversFolder(String driversFolder) {
+        this.driversFolder = driversFolder;
+    }
+
+    /**
+     * @return {@code true} If agent options usage should be printed.
+     */
+    public Boolean help() {
+        return help != null ? help : false;
+    }
+
+    /**
+     * @param cfgUrl URL.
+     */
+    public void load(URL cfgUrl) throws IOException {
+        Properties props = new Properties();
+
+        try (Reader reader = new InputStreamReader(cfgUrl.openStream())) {
+            props.load(reader);
+        }
+
+        String val = (String)props.remove("token");
+
+        if (val != null)
+            token(val);
+
+        val = (String)props.remove("server-uri");
+
+        if (val != null)
+            serverUri(val);
+
+        val = (String)props.remove("node-uri");
+
+        if (val != null)
+            nodeUri(val);
+
+        val = (String)props.remove("driver-folder");
+
+        if (val != null)
+            driversFolder(val);
+    }
+
+    /**
+     * @param cmd Command.
+     */
+    public void merge(AgentConfiguration cmd) {
+        if (tok == null)
+            token(cmd.token());
+
+        if (srvUri == null)
+            serverUri(cmd.serverUri());
+
+        if (srvUri == null)
+            serverUri(DFLT_SERVER_URI);
+
+        if (nodeUri == null)
+            nodeUri(cmd.nodeUri());
+
+        if (nodeUri == null)
+            nodeUri(DFLT_NODE_URI);
+
+        if (driversFolder == null)
+            driversFolder(cmd.driversFolder());
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        StringBuilder sb = new StringBuilder();
+
+        if (tok != null && tok.length() > 0) {
+            sb.append("User's security token         : ");
+
+            if (tok.length() > 4) {
+                sb.append(new String(new char[tok.length() - 4]).replace("\0", "*"));
+
+                sb.append(tok.substring(tok.length() - 4));
+            }
+            else
+                sb.append(new String(new char[tok.length()]).replace("\0", "*"));
+
+            sb.append('\n');
+        }
+
+        sb.append("URI to Ignite node REST server: ").append(nodeUri == null ? DFLT_NODE_URI : nodeUri).append('\n');
+        sb.append("URI to Ignite Console server  : ").append(srvUri == null ? DFLT_SERVER_URI : srvUri).append('\n');
+        sb.append("Path to agent property file   : ").append(configPath()).append('\n');
+
+        String drvFld = driversFolder();
+
+        if (drvFld == null) {
+            File agentHome = AgentUtils.getAgentHome();
+
+            if (agentHome != null)
+                drvFld = new File(agentHome, "jdbc-drivers").getPath();
+        }
+
+        sb.append("Path to JDBC drivers folder   : ").append(drvFld);
+
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentLauncher.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentLauncher.java b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentLauncher.java
new file mode 100644
index 0000000..ed08d78
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentLauncher.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.console.agent;
+
+import com.beust.jcommander.JCommander;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+
+import com.beust.jcommander.ParameterException;
+import org.apache.ignite.console.agent.handlers.RestExecutor;
+import org.apache.log4j.Logger;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.websocket.client.WebSocketClient;
+
+import static org.apache.ignite.console.agent.AgentConfiguration.DFLT_SERVER_PORT;
+
+/**
+ * Control Center Agent launcher.
+ */
+public class AgentLauncher {
+    /** */
+    private static final Logger log = Logger.getLogger(AgentLauncher.class.getName());
+
+    /** */
+    private static final int RECONNECT_INTERVAL = 3000;
+
+    /**
+     * @param args Args.
+     */
+    @SuppressWarnings("BusyWait")
+    public static void main(String[] args) throws Exception {
+        log.info("Starting Apache Ignite Web Console Agent...");
+
+        AgentConfiguration cfg = new AgentConfiguration();
+
+        JCommander jCommander = new JCommander(cfg);
+
+        String osName = System.getProperty("os.name").toLowerCase();
+
+        jCommander.setProgramName("ignite-web-agent." + (osName.contains("win") ? "bat" : "sh"));
+
+        try {
+            jCommander.parse(args);
+        }
+        catch (ParameterException pe) {
+            log.error("Failed to parse command line parameters: " + Arrays.toString(args), pe);
+
+            jCommander.usage();
+
+            return;
+        }
+
+        String prop = cfg.configPath();
+
+        AgentConfiguration propCfg = new AgentConfiguration();
+
+        try {
+            File f = AgentUtils.resolvePath(prop);
+
+            if (f == null)
+                log.warn("Failed to find agent property file: '" + prop + "'");
+            else
+                propCfg.load(f.toURI().toURL());
+        }
+        catch (IOException ignore) {
+            if (!AgentConfiguration.DFLT_CFG_PATH.equals(prop))
+                log.warn("Failed to load agent property file: '" + prop + "'", ignore);
+        }
+
+        cfg.merge(propCfg);
+
+        if (cfg.help()) {
+            jCommander.usage();
+
+            return;
+        }
+
+        System.out.println();
+        System.out.println("Agent configuration:");
+        System.out.println(cfg);
+        System.out.println();
+
+        if (cfg.token() == null) {
+            String webHost;
+
+            try {
+                webHost = new URI(cfg.serverUri()).getHost();
+            }
+            catch (URISyntaxException e) {
+                log.error("Failed to parse Ignite Web Console uri", e);
+
+                return;
+            }
+
+            System.out.println("Security token is required to establish connection to the web console.");
+            System.out.println(String.format("It is available on the Profile page: https://%s/profile", webHost));
+
+            System.out.print("Enter security token: ");
+
+            cfg.token(System.console().readLine().trim());
+        }
+
+        RestExecutor restExecutor = new RestExecutor(cfg);
+
+        restExecutor.start();
+
+        try {
+            SslContextFactory sslCtxFactory = new SslContextFactory();
+
+            // Workaround for use self-signed certificate:
+            if (Boolean.getBoolean("trust.all"))
+                sslCtxFactory.setTrustAll(true);
+
+            WebSocketClient client = new WebSocketClient(sslCtxFactory);
+
+            client.setMaxIdleTimeout(Long.MAX_VALUE);
+
+            client.start();
+
+            try {
+                while (!Thread.interrupted()) {
+                    AgentSocket agentSock = new AgentSocket(cfg, restExecutor);
+
+                    log.info("Connecting to: " + cfg.serverUri());
+
+                    URI uri = URI.create(cfg.serverUri());
+
+                    if (uri.getPort() == -1)
+                        uri = URI.create(cfg.serverUri() + ":" + DFLT_SERVER_PORT);
+
+                    client.connect(agentSock, uri);
+
+                    agentSock.waitForClose();
+
+                    Thread.sleep(RECONNECT_INTERVAL);
+                }
+            }
+            finally {
+                client.stop();
+            }
+        }
+        finally {
+            restExecutor.stop();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentSocket.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentSocket.java b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentSocket.java
new file mode 100644
index 0000000..80816fa
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentSocket.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.console.agent;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.concurrent.CountDownLatch;
+import javax.net.ssl.SSLHandshakeException;
+import org.apache.ignite.console.agent.handlers.DatabaseMetadataExtractor;
+import org.apache.ignite.console.agent.handlers.RestExecutor;
+import org.apache.ignite.console.agent.remote.Remote;
+import org.apache.ignite.console.agent.remote.RemoteHandler;
+import org.apache.ignite.console.agent.remote.WebSocketSender;
+import org.apache.log4j.Logger;
+import org.eclipse.jetty.websocket.api.Session;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.WebSocket;
+
+/**
+ * Handler for web-socket connection.
+ */
+@WebSocket
+public class AgentSocket implements WebSocketSender {
+    /** */
+    public static final Gson GSON = new Gson();
+
+    /** */
+    public static final JsonParser PARSER = new JsonParser();
+
+    /** */
+    private static final Logger log = Logger.getLogger(AgentSocket.class.getName());
+
+    /** */
+    private final CountDownLatch closeLatch = new CountDownLatch(1);
+
+    /** */
+    private final AgentConfiguration cfg;
+
+    /** */
+    private final RestExecutor restExecutor;
+
+    /** */
+    private RemoteHandler remote;
+
+    /** */
+    private Session ses;
+
+    /**
+     * @param cfg Config.
+     */
+    public AgentSocket(AgentConfiguration cfg, RestExecutor restExecutor) {
+        this.cfg = cfg;
+        this.restExecutor = restExecutor;
+    }
+
+    /**
+     * @param statusCode Status code.
+     * @param reason Reason.
+     */
+    @OnWebSocketClose
+    public void onClose(int statusCode, String reason) {
+        log.warn(String.format("Connection closed: %d - %s.", statusCode, reason));
+
+        if (remote != null)
+            remote.close();
+
+        closeLatch.countDown();
+    }
+
+    /**
+     * @param ses Session.
+     */
+    @OnWebSocketConnect
+    public void onConnect(Session ses) {
+        log.info("Connection established.");
+
+        this.ses = ses;
+
+        remote = RemoteHandler.wrap(this, this, restExecutor, new DatabaseMetadataExtractor(cfg));
+
+        JsonObject authMsg = new JsonObject();
+
+        authMsg.addProperty("type", "AuthMessage");
+        authMsg.addProperty("token", cfg.token());
+
+        send(authMsg);
+    }
+
+    /**
+     * @param msg Message.
+     * @return Whether or not message was sent.
+     */
+    @Override public boolean send(JsonObject msg) {
+        return send(GSON.toJson(msg));
+    }
+
+    /**
+     * @param msg Message.
+     * @return Whether or not message was sent.
+     */
+    @Override public boolean send(String msg) {
+        try {
+            ses.getRemote().sendString(msg);
+
+            return true;
+        }
+        catch (IOException ignored) {
+            log.error("Failed to send message to Control Center.");
+
+            return false;
+        }
+    }
+
+    /**
+     * @param ses Session.
+     * @param error Error.
+     */
+    @OnWebSocketError
+    public void onError(Session ses, Throwable error) {
+        if (error instanceof ConnectException)
+            log.warn(error.getMessage());
+        else if (error instanceof SSLHandshakeException) {
+            log.error("Failed to establish SSL connection to Ignite Console. Start agent with " +
+                "\"-Dtrust.all=true\" to skip certificate validation in case of using self-signed certificate.", error);
+
+            System.exit(1);
+        }
+        else
+            log.error("Connection error.", error);
+
+        if (remote != null)
+            remote.close();
+
+        closeLatch.countDown();
+    }
+
+    /**
+     * @param msg Message.
+     */
+    @OnWebSocketMessage
+    public void onMessage(String msg) {
+        JsonElement jsonElement = PARSER.parse(msg);
+
+        remote.onMessage((JsonObject)jsonElement);
+    }
+
+    /**
+     * @param errorMsg Authentication failed message or {@code null} if authentication success.
+     */
+    @Remote
+    public void authResult(String errorMsg) {
+        if (errorMsg != null) {
+            onClose(401, "Authentication failed: " + errorMsg);
+
+            System.exit(1);
+        }
+
+        log.info("Authentication success.");
+    }
+
+    /**
+     * Await socket close.
+     */
+    public void waitForClose() throws InterruptedException {
+        closeLatch.await();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentUtils.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentUtils.java b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentUtils.java
new file mode 100644
index 0000000..349eea1
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/AgentUtils.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.console.agent;
+
+import org.apache.log4j.Logger;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.ProtectionDomain;
+
+/**
+ * Utility methods.
+ */
+public class AgentUtils {
+    /** */
+    private static final Logger log = Logger.getLogger(AgentUtils.class.getName());
+
+    /**
+     * Default constructor.
+     */
+    private AgentUtils() {
+        // No-op.
+    }
+
+    /**
+     * @param path Path to normalize.
+     * @return Normalized file path.
+     */
+    public static String normalizePath(String path) {
+        return path != null ? path.replace('\\', '/') : null;
+    }
+
+    /**
+     * @return App folder.
+     */
+    public static File getAgentHome() {
+        try {
+            ProtectionDomain domain = AgentLauncher.class.getProtectionDomain();
+
+            // Should not happen, but to make sure our code is not broken.
+            if (domain == null || domain.getCodeSource() == null || domain.getCodeSource().getLocation() == null) {
+                log.warn("Failed to resolve agent jar location!");
+
+                return null;
+            }
+
+            // Resolve path to class-file.
+            URI classesUri = domain.getCodeSource().getLocation().toURI();
+
+            boolean win = System.getProperty("os.name").toLowerCase().contains("win");
+
+            // Overcome UNC path problem on Windows (http://www.tomergabel.com/JavaMishandlesUNCPathsOnWindows.aspx)
+            if (win && classesUri.getAuthority() != null)
+                classesUri = new URI(classesUri.toString().replace("file://", "file:/"));
+
+            return new File(classesUri).getParentFile();
+        }
+        catch (URISyntaxException | SecurityException ignored) {
+            log.warn("Failed to resolve agent jar location!");
+
+            return null;
+        }
+    }
+
+    /**
+     * Gets file associated with path.
+     * <p>
+     * First check if path is relative to agent home.
+     * If not, check if path is absolute.
+     * If all checks fail, then {@code null} is returned.
+     * <p>
+     *
+     * @param path Path to resolve.
+     * @return Resolved path as file, or {@code null} if path cannot be resolved.
+     */
+    public static File resolvePath(String path) {
+        assert path != null;
+
+        File home = getAgentHome();
+
+        if (home != null) {
+            File file = new File(home, normalizePath(path));
+
+            if (file.exists())
+                return file;
+        }
+
+        /*
+         * 2. Check given path as absolute.
+         */
+
+        File file = new File(path);
+
+        if (file.exists())
+            return file;
+
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseMetadataExtractor.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseMetadataExtractor.java b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseMetadataExtractor.java
new file mode 100644
index 0000000..48d5236
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseMetadataExtractor.java
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.console.agent.handlers;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import org.apache.ignite.console.agent.AgentConfiguration;
+import org.apache.ignite.console.agent.remote.Remote;
+import org.apache.ignite.console.demo.AgentMetadataDemo;
+import org.apache.ignite.schema.parser.DbMetadataReader;
+import org.apache.ignite.schema.parser.DbTable;
+import org.apache.log4j.Logger;
+
+import static org.apache.ignite.console.agent.AgentUtils.resolvePath;
+
+/**
+ * Remote API to extract database metadata.
+ */
+public class DatabaseMetadataExtractor {
+    /** */
+    private static final Logger log = Logger.getLogger(DatabaseMetadataExtractor.class.getName());
+
+    /** */
+    private final File driversFolder;
+
+    /**
+     * @param cfg Config.
+     */
+    public DatabaseMetadataExtractor(AgentConfiguration cfg) {
+        driversFolder = resolvePath(cfg.driversFolder() == null ? "jdbc-drivers" : cfg.driversFolder());
+    }
+
+    /**
+     * @param jdbcDriverJarPath JDBC driver JAR path.
+     * @param jdbcDriverCls JDBC driver class.
+     * @param jdbcUrl JDBC URL.
+     * @param jdbcInfo Properties to connect to database.
+     * @return Connection to database.
+     * @throws SQLException
+     */
+    private Connection connect(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl, Properties jdbcInfo) throws SQLException {
+        if (!new File(jdbcDriverJarPath).isAbsolute() && driversFolder != null)
+            jdbcDriverJarPath = new File(driversFolder, jdbcDriverJarPath).getPath();
+
+        if (AgentMetadataDemo.isTestDriveUrl(jdbcUrl))
+            AgentMetadataDemo.testDrive();
+
+        return DbMetadataReader.getInstance().connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo);
+    }
+
+    /**
+     * @param jdbcDriverJarPath JDBC driver JAR path.
+     * @param jdbcDriverCls JDBC driver class.
+     * @param jdbcUrl JDBC URL.
+     * @param jdbcInfo Properties to connect to database.
+     * @return Collection of schema names.
+     * @throws SQLException
+     */
+    @Remote
+    public Collection<String> schemas(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
+        Properties jdbcInfo) throws SQLException {
+        log.debug("Start collecting database schemas [driver jar=" + jdbcDriverJarPath +
+            ", driver class=" + jdbcDriverCls + ", url=" + jdbcUrl + "]");
+
+        try (Connection conn = connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo)) {
+            Collection<String> schemas = DbMetadataReader.getInstance().schemas(conn);
+
+            log.debug("Finished collection of schemas [url=" + jdbcUrl + ", count="+ schemas.size() +"]");
+
+            return schemas;
+        }
+        catch (Throwable e) {
+            log.error("Failed to collect schemas", e);
+
+            throw new SQLException("Failed to collect schemas", e);
+        }
+    }
+
+    /**
+     * @param jdbcDriverJarPath JDBC driver JAR path.
+     * @param jdbcDriverCls JDBC driver class.
+     * @param jdbcUrl JDBC URL.
+     * @param jdbcInfo Properties to connect to database.
+     * @param schemas List of schema names to process.
+     * @param tblsOnly If {@code true} then only tables will be processed otherwise views also will be processed.
+     * @return Collection of tables.
+     */
+    @Remote
+    public Collection<DbTable> metadata(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
+        Properties jdbcInfo, List<String> schemas, boolean tblsOnly) throws SQLException {
+        log.debug("Start collecting database metadata [driver jar=" + jdbcDriverJarPath +
+            ", driver class=" + jdbcDriverCls + ", url=" + jdbcUrl + "]");
+
+        try (Connection conn = connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo)) {
+            Collection<DbTable> metadata = DbMetadataReader.getInstance().metadata(conn, schemas, tblsOnly);
+
+            log.debug("Finished collection of metadata [url=" + jdbcUrl + ", count="+ metadata.size() +"]");
+
+            return metadata;
+        }
+        catch (Throwable e) {
+            log.error("Failed to collect metadata", e);
+
+            throw new SQLException("Failed to collect metadata", e);
+        }
+    }
+
+    /**
+     * @return Drivers in drivers folder
+     * @see AgentConfiguration#driversFolder
+     */
+    @Remote
+    public List<JdbcDriver> availableDrivers() {
+        if (driversFolder == null) {
+            log.info("JDBC drivers folder not specified, returning empty list");
+
+            return Collections.emptyList();
+        }
+
+        log.debug("Collecting JDBC drivers in folder: " + driversFolder.getPath());
+
+        File[] list = driversFolder.listFiles(new FilenameFilter() {
+            @Override public boolean accept(File dir, String name) {
+                return name.endsWith(".jar");
+            }
+        });
+
+        if (list == null) {
+            log.info("JDBC drivers folder has no files, returning empty list");
+
+            return Collections.emptyList();
+        }
+
+        List<JdbcDriver> res = new ArrayList<>();
+
+        for (File file : list) {
+            try {
+                boolean win = System.getProperty("os.name").contains("win");
+
+                URL url = new URL("jar", null, "file:" + (win ? "/" : "") + file.getPath() + "!/META-INF/services/java.sql.Driver");
+
+                try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
+                    String jdbcDriverCls = reader.readLine();
+
+                    res.add(new JdbcDriver(file.getName(), jdbcDriverCls));
+
+                    log.debug("Found: [driver=" + file + ", class=" + jdbcDriverCls + "]");
+                }
+            }
+            catch (IOException e) {
+                res.add(new JdbcDriver(file.getName(), null));
+
+                log.info("Found: [driver=" + file + "]");
+                log.info("Failed to detect driver class: " + e.getMessage());
+            }
+        }
+
+        return res;
+    }
+
+    /**
+     * Wrapper class for later to be transformed to JSON and send to Web Console.
+     */
+    private static class JdbcDriver {
+        /** */
+        private final String jdbcDriverJar;
+        /** */
+        private final String jdbcDriverClass;
+
+        /**
+         * @param jdbcDriverJar File name of driver jar file.
+         * @param jdbcDriverClass Optional JDBC driver class.
+         */
+        public JdbcDriver(String jdbcDriverJar, String jdbcDriverClass) {
+            this.jdbcDriverJar = jdbcDriverJar;
+            this.jdbcDriverClass = jdbcDriverClass;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestExecutor.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestExecutor.java b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestExecutor.java
new file mode 100644
index 0000000..ee6742a
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestExecutor.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.console.agent.handlers;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.codec.Charsets;
+import org.apache.http.Header;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.ignite.console.agent.AgentConfiguration;
+import org.apache.ignite.console.agent.remote.Remote;
+import org.apache.ignite.console.demo.AgentSqlDemo;
+import org.apache.log4j.Logger;
+
+import static org.apache.ignite.console.agent.AgentConfiguration.DFLT_NODE_PORT;
+
+/**
+ * Executor for REST requests.
+ */
+public class RestExecutor {
+    /** */
+    private static final Logger log = Logger.getLogger(RestExecutor.class.getName());
+
+    /** */
+    private final AgentConfiguration cfg;
+
+    /** */
+    private CloseableHttpClient httpClient;
+
+    /**
+     * @param cfg Config.
+     */
+    public RestExecutor(AgentConfiguration cfg) {
+        this.cfg = cfg;
+    }
+
+    /**
+     *
+     */
+    public void start() {
+        httpClient = HttpClientBuilder.create().build();
+    }
+
+    /**
+     *
+     */
+    public void stop() throws IOException {
+        if (httpClient != null)
+            httpClient.close();
+    }
+
+    /**
+     * @param uri Url.
+     * @param params Params.
+     * @param demo Use demo node.
+     * @param mtd Method.
+     * @param headers Headers.
+     * @param body Body.
+     */
+    @Remote
+    public RestResult executeRest(String uri, Map<String, String> params, boolean demo,
+        String mtd, Map<String, String> headers, String body) throws IOException, URISyntaxException {
+        log.debug("Start execute REST command [method=" + mtd + ", uri=/" + uri + ", parameters=" + params + "]");
+
+        URIBuilder builder = new URIBuilder(demo ? cfg.demoNodeUri() : cfg.nodeUri());
+
+        if (builder.getPort() == -1)
+            builder.setPort(DFLT_NODE_PORT);
+
+        if (uri != null) {
+            if (!uri.startsWith("/") && !cfg.nodeUri().endsWith("/"))
+                uri = '/' + uri;
+
+            builder.setPath(uri);
+        }
+
+        if (params != null) {
+            for (Map.Entry<String, String> entry : params.entrySet())
+                builder.addParameter(entry.getKey(), entry.getValue());
+        }
+
+        HttpRequestBase httpReq;
+
+        if ("GET".equalsIgnoreCase(mtd))
+            httpReq = new HttpGet(builder.build());
+        else if ("POST".equalsIgnoreCase(mtd)) {
+            HttpPost post;
+
+            if (body == null) {
+                List<NameValuePair> nvps = builder.getQueryParams();
+
+                builder.clearParameters();
+
+                post = new HttpPost(builder.build());
+
+                if (!nvps.isEmpty())
+                    post.setEntity(new UrlEncodedFormEntity(nvps));
+            }
+            else {
+                post = new HttpPost(builder.build());
+
+                post.setEntity(new StringEntity(body));
+            }
+
+            httpReq = post;
+        }
+        else
+            throw new IOException("Unknown HTTP-method: " + mtd);
+
+        if (headers != null) {
+            for (Map.Entry<String, String> entry : headers.entrySet())
+                httpReq.addHeader(entry.getKey(), entry.getValue());
+        }
+
+        try (CloseableHttpResponse resp = httpClient.execute(httpReq)) {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+            resp.getEntity().writeTo(out);
+
+            Charset charset = Charsets.UTF_8;
+
+            Header encodingHdr = resp.getEntity().getContentEncoding();
+
+            if (encodingHdr != null) {
+                String encoding = encodingHdr.getValue();
+
+                charset = Charsets.toCharset(encoding);
+            }
+
+            return new RestResult(resp.getStatusLine().getStatusCode(), new String(out.toByteArray(), charset));
+        }
+        catch (ConnectException e) {
+            log.debug("Failed connect to node and execute REST command [uri=" + builder.build() + "]");
+
+            return new RestResult(404, "Failed connect to node and execute REST command.");
+        }
+    }
+
+    /**
+     * Enable test-drive SQL.
+     */
+    @Remote
+    public boolean startDemoSQL() {
+        return AgentSqlDemo.testDrive(cfg);
+    }
+
+    /**
+     * Request result.
+     */
+    public static class RestResult {
+        /** Status code. */
+        private int code;
+
+        /** Message. */
+        private String message;
+
+        /**
+         * @param code Code.
+         * @param msg Message.
+         */
+        public RestResult(int code, String msg) {
+            this.code = code;
+            message = msg;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/54a24746/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/remote/Remote.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/remote/Remote.java b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/remote/Remote.java
new file mode 100644
index 0000000..71b2bc0
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/console/agent/remote/Remote.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.console.agent.remote;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation to associate methods with remote NodeJS server commands.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Remote {
+    /**
+     * Whether or not method should be executed synchronously.
+     *
+     * @return {@code true} if method will be executed in separated thread otherwise if method will be executed in handler thread.
+     */
+    boolean async() default true;
+}