Introduction

Java programs can connect to virtually any relational (and many non-relational) databases as well as tabular data in files. This tutorial provides an overview of the different approaches to working with data in databases.

Sample Code

The sample code below shows how to connect to a SQLite database using JDBC and issue a SQL SELECT statement to retrieve data and then access the result set. However, the code is procedural and not object-oriented. In practice, one must create an object-relational layer and saving and loading of data should be done within the object through dedicated methods and in the constructor.

SQLite Database Java Source Code

Running the code requires downloading and importing the SQLite package.


/*
 * Example: Connect to SQLite Database
 *
 * Requires SQLite JDBC Driver from 
 * https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc
 * to be added to CLASSPATH or IDE Libraries
 */

package sqliteconnect;

/**
 *
 * @author Martin Schedlbauer, PhD
 */

import java.sql.*;

public class SQLiteConnect {
    
    public static Connection connect (String db) 
    {
        
        try{
            Class.forName("org.sqlite.JDBC");
        }catch(ClassNotFoundException e) {
            System.out.println("jdbc driver missing");
        }
        
        Connection conn = null;
        try {
            // db parameters
            String url = "jdbc:sqlite:" + db;
            // create a connection to the database
            conn = DriverManager.getConnection(url);
            
            System.out.println("Connection to SQLite has been established.");
            
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        
        return (conn);
    }
    
    public static ResultSet retrieveCourses(Connection conn) 
    {
        ResultSet rs = null;

        try {
            Statement stmt = conn.createStatement();
            rs = stmt.executeQuery("SELECT * FROM Courses");
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }

        return (rs);
    }
    
    public static ResultSet retrieveCourse(Connection conn, int cid) 
    {
        ResultSet rs = null;

        try {
            String sql = "SELECT * FROM Courses WHERE cid = ?";
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setInt (1, cid);
            rs = ps.executeQuery();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }

        return (rs);
    }
    
    public static int addCourse(Connection conn, 
                                int cid, String title, String dept, int cr) 
    {
        int n = 0;

        try {
            String insertSQL = "INSERT INTO Courses VALUES(?,?,?,?)";
            PreparedStatement ps = conn.prepareStatement(insertSQL);
            ps.setInt(1,cid);
            ps.setString(2,title);
            ps.setString(3,dept);
            ps.setInt(4,cr);
            n = ps.executeUpdate();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }

        return (n);
    }
    
    public static int removeCourse(Connection conn, int cid) 
    {
        int n = 0;

        try {
            String updateSQL = "DELETE FROM Courses WHERE cid = ?";
            PreparedStatement ps = conn.prepareStatement(updateSQL);
            ps.setInt(1,cid);
            n = ps.executeUpdate();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }

        return (n);
    }
    
    public static void printResultSet (ResultSet rs)
    {
        try {
            ResultSetMetaData rsmd = rs.getMetaData();
            int columnsNumber = rsmd.getColumnCount();
            while (rs.next()) {
                for (int i = 1; i <= columnsNumber; i++) {
                    if (i > 1) {
                        System.out.print(",  ");
                    }
                    String columnValue = rs.getString(i);
                    System.out.print(columnValue + " " + rsmd.getColumnName(i));
                }
                System.out.println("");
            }

            while (rs.next()) {
                String title = rs.getString("title");
                System.out.println(title);
            }
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
    
    public static void main(String[] args) 
    {
        System.out.println("connecting to sqlite db...");
        
        String sqliteDB = "courseDB.db";
        Connection conn = connect (sqliteDB);
        
        System.out.println("retrieving all courses...");
        printResultSet (retrieveCourses (conn));
        
        System.out.println("removing course cid = 404...");
        removeCourse (conn, 404);
        
        System.out.println("adding new course...");
        addCourse (conn, 404, "Theory of Computation", "CS", 3);
        
        System.out.println("retrieving new course...");
        printResultSet (retrieveCourse (conn, 404));
    }
}

Conclusion


Files & Resources

All Files for Lesson 9.602

Errata

None collected yet. Let us know.

LS0tDQp0aXRsZTogIldvcmtpbmcgd2l0aCBEYXRhYmFzZXMgaW4gSmF2YSINCnBhcmFtczoNCiAgY2F0ZWdvcnk6IDkNCiAgbnVtYmVyOiA2MDINCiAgdGltZTogMjANCiAgbGV2ZWw6IGJlZ2lubmVyDQogIHRhZ3M6ICJKYXZhLFNRTCxzcWxpdGUsSkRCQyINCiAgZGVzY3JpcHRpb246ICJEZW1vbnN0cmF0ZXMgaG93IHRvIGNvbm5lY3QgdG8gZGF0YWJhc2VzIGluIEphdmEgdXNpbmcNCiAgICAgICAgICAgICAgICBTUUxpdGUgYXMgYW4gZXhhbXBsZS4gU2hvd3MgaG93IHRvIGNvbm5lY3QsIGNyZWF0ZSANCiAgICAgICAgICAgICAgICB0YWJsZXMsIGV4ZWN1dGUgU1FMIHF1ZXJpZXMsIG1vZGlmeSB0aGUgZGF0YSwgYW5kIA0KICAgICAgICAgICAgICAgIGVucXVpcmUgYWJvdXQgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YWJhc2UuIA0KICAgICAgICAgICAgICAgICINCmRhdGU6ICI8c21hbGw+YHIgU3lzLkRhdGUoKWA8L3NtYWxsPiINCmF1dGhvcjogIjxzbWFsbD5NYXJ0aW4gU2NoZWRsYmF1ZXI8L3NtYWxsPiINCmVtYWlsOiAibS5zY2hlZGxiYXVlckBuZXUuZWR1Ig0KYWZmaWxpdGF0aW9uOiAiTm9ydGhlYXN0ZXJuIFVuaXZlcnNpdHkiDQpvdXRwdXQ6IA0KICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29sbGFwc2VkOiBmYWxzZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdGhlbWU6IHNwYWNlbGFiDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KLS0tDQoNCi0tLQ0KdGl0bGU6ICI8c21hbGw+YHIgcGFyYW1zJGNhdGVnb3J5YC5gciBwYXJhbXMkbnVtYmVyYDwvc21hbGw+PGJyLz48c3BhbiBzdHlsZT0nY29sb3I6ICMyRTQwNTM7IGZvbnQtc2l6ZTogMC45ZW0nPmByIHJtYXJrZG93bjo6bWV0YWRhdGEkdGl0bGVgPC9zcGFuPiINCi0tLQ0KDQpgYGB7ciBjb2RlPXhmdW46OnJlYWRfdXRmOChwYXN0ZTAoaGVyZTo6aGVyZSgpLCcvUi9faW5zZXJ0MkRCLlInKSksIGluY2x1ZGUgPSBGQUxTRX0NCmBgYA0KDQojIyBJbnRyb2R1Y3Rpb24NCg0KSmF2YSBwcm9ncmFtcyBjYW4gY29ubmVjdCB0byB2aXJ0dWFsbHkgYW55IHJlbGF0aW9uYWwgKGFuZCBtYW55IG5vbi1yZWxhdGlvbmFsKSBkYXRhYmFzZXMgYXMgd2VsbCBhcyB0YWJ1bGFyIGRhdGEgaW4gZmlsZXMuIFRoaXMgdHV0b3JpYWwgcHJvdmlkZXMgYW4gb3ZlcnZpZXcgb2YgdGhlIGRpZmZlcmVudCBhcHByb2FjaGVzIHRvIHdvcmtpbmcgd2l0aCBkYXRhIGluIGRhdGFiYXNlcy4NCg0KIyMgU2FtcGxlIENvZGUNCg0KVGhlIHNhbXBsZSBjb2RlIGJlbG93IHNob3dzIGhvdyB0byBjb25uZWN0IHRvIGEgU1FMaXRlIGRhdGFiYXNlIHVzaW5nIEpEQkMgYW5kIGlzc3VlIGEgU1FMIFNFTEVDVCBzdGF0ZW1lbnQgdG8gcmV0cmlldmUgZGF0YSBhbmQgdGhlbiBhY2Nlc3MgdGhlIHJlc3VsdCBzZXQuIEhvd2V2ZXIsIHRoZSBjb2RlIGlzIHByb2NlZHVyYWwgYW5kIG5vdCBvYmplY3Qtb3JpZW50ZWQuIEluIHByYWN0aWNlLCBvbmUgbXVzdCBjcmVhdGUgYW4gb2JqZWN0LXJlbGF0aW9uYWwgbGF5ZXIgYW5kIHNhdmluZyBhbmQgbG9hZGluZyBvZiBkYXRhIHNob3VsZCBiZSBkb25lIHdpdGhpbiB0aGUgb2JqZWN0IHRocm91Z2ggZGVkaWNhdGVkIG1ldGhvZHMgYW5kIGluIHRoZSBjb25zdHJ1Y3Rvci4NCg0KW1NRTGl0ZSBEYXRhYmFzZV0oY291cnNlREIuZGIpIFtKYXZhIFNvdXJjZSBDb2RlXShTUUxpdGVDb25uZWN0LmphdmEpDQoNClJ1bm5pbmcgdGhlIGNvZGUgcmVxdWlyZXMgZG93bmxvYWRpbmcgYW5kIGltcG9ydGluZyB0aGUgU1FMaXRlIHBhY2thZ2UuDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpgYGB7amF2YSwgZXZhbD1GfQ0KLyoNCiAqIEV4YW1wbGU6IENvbm5lY3QgdG8gU1FMaXRlIERhdGFiYXNlDQogKg0KICogUmVxdWlyZXMgU1FMaXRlIEpEQkMgRHJpdmVyIGZyb20gDQogKiBodHRwczovL212bnJlcG9zaXRvcnkuY29tL2FydGlmYWN0L29yZy54ZXJpYWwvc3FsaXRlLWpkYmMNCiAqIHRvIGJlIGFkZGVkIHRvIENMQVNTUEFUSCBvciBJREUgTGlicmFyaWVzDQogKi8NCg0KcGFja2FnZSBzcWxpdGVjb25uZWN0Ow0KDQovKioNCiAqDQogKiBAYXV0aG9yIE1hcnRpbiBTY2hlZGxiYXVlciwgUGhEDQogKi8NCg0KaW1wb3J0IGphdmEuc3FsLio7DQoNCnB1YmxpYyBjbGFzcyBTUUxpdGVDb25uZWN0IHsNCiAgICANCiAgICBwdWJsaWMgc3RhdGljIENvbm5lY3Rpb24gY29ubmVjdCAoU3RyaW5nIGRiKSANCiAgICB7DQogICAgICAgIA0KICAgICAgICB0cnl7DQogICAgICAgICAgICBDbGFzcy5mb3JOYW1lKCJvcmcuc3FsaXRlLkpEQkMiKTsNCiAgICAgICAgfWNhdGNoKENsYXNzTm90Rm91bmRFeGNlcHRpb24gZSkgew0KICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJqZGJjIGRyaXZlciBtaXNzaW5nIik7DQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIENvbm5lY3Rpb24gY29ubiA9IG51bGw7DQogICAgICAgIHRyeSB7DQogICAgICAgICAgICAvLyBkYiBwYXJhbWV0ZXJzDQogICAgICAgICAgICBTdHJpbmcgdXJsID0gImpkYmM6c3FsaXRlOiIgKyBkYjsNCiAgICAgICAgICAgIC8vIGNyZWF0ZSBhIGNvbm5lY3Rpb24gdG8gdGhlIGRhdGFiYXNlDQogICAgICAgICAgICBjb25uID0gRHJpdmVyTWFuYWdlci5nZXRDb25uZWN0aW9uKHVybCk7DQogICAgICAgICAgICANCiAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiQ29ubmVjdGlvbiB0byBTUUxpdGUgaGFzIGJlZW4gZXN0YWJsaXNoZWQuIik7DQogICAgICAgICAgICANCiAgICAgICAgfSBjYXRjaCAoU1FMRXhjZXB0aW9uIGUpIHsNCiAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbihlLmdldE1lc3NhZ2UoKSk7DQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIHJldHVybiAoY29ubik7DQogICAgfQ0KICAgIA0KICAgIHB1YmxpYyBzdGF0aWMgUmVzdWx0U2V0IHJldHJpZXZlQ291cnNlcyhDb25uZWN0aW9uIGNvbm4pIA0KICAgIHsNCiAgICAgICAgUmVzdWx0U2V0IHJzID0gbnVsbDsNCg0KICAgICAgICB0cnkgew0KICAgICAgICAgICAgU3RhdGVtZW50IHN0bXQgPSBjb25uLmNyZWF0ZVN0YXRlbWVudCgpOw0KICAgICAgICAgICAgcnMgPSBzdG10LmV4ZWN1dGVRdWVyeSgiU0VMRUNUICogRlJPTSBDb3Vyc2VzIik7DQogICAgICAgIH0gY2F0Y2ggKFNRTEV4Y2VwdGlvbiBlKSB7DQogICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oZS5nZXRNZXNzYWdlKCkpOw0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuIChycyk7DQogICAgfQ0KICAgIA0KICAgIHB1YmxpYyBzdGF0aWMgUmVzdWx0U2V0IHJldHJpZXZlQ291cnNlKENvbm5lY3Rpb24gY29ubiwgaW50IGNpZCkgDQogICAgew0KICAgICAgICBSZXN1bHRTZXQgcnMgPSBudWxsOw0KDQogICAgICAgIHRyeSB7DQogICAgICAgICAgICBTdHJpbmcgc3FsID0gIlNFTEVDVCAqIEZST00gQ291cnNlcyBXSEVSRSBjaWQgPSA/IjsNCiAgICAgICAgICAgIFByZXBhcmVkU3RhdGVtZW50IHBzID0gY29ubi5wcmVwYXJlU3RhdGVtZW50KHNxbCk7DQogICAgICAgICAgICBwcy5zZXRJbnQgKDEsIGNpZCk7DQogICAgICAgICAgICBycyA9IHBzLmV4ZWN1dGVRdWVyeSgpOw0KICAgICAgICB9IGNhdGNoIChTUUxFeGNlcHRpb24gZSkgew0KICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKGUuZ2V0TWVzc2FnZSgpKTsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAocnMpOw0KICAgIH0NCiAgICANCiAgICBwdWJsaWMgc3RhdGljIGludCBhZGRDb3Vyc2UoQ29ubmVjdGlvbiBjb25uLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50IGNpZCwgU3RyaW5nIHRpdGxlLCBTdHJpbmcgZGVwdCwgaW50IGNyKSANCiAgICB7DQogICAgICAgIGludCBuID0gMDsNCg0KICAgICAgICB0cnkgew0KICAgICAgICAgICAgU3RyaW5nIGluc2VydFNRTCA9ICJJTlNFUlQgSU5UTyBDb3Vyc2VzIFZBTFVFUyg/LD8sPyw/KSI7DQogICAgICAgICAgICBQcmVwYXJlZFN0YXRlbWVudCBwcyA9IGNvbm4ucHJlcGFyZVN0YXRlbWVudChpbnNlcnRTUUwpOw0KICAgICAgICAgICAgcHMuc2V0SW50KDEsY2lkKTsNCiAgICAgICAgICAgIHBzLnNldFN0cmluZygyLHRpdGxlKTsNCiAgICAgICAgICAgIHBzLnNldFN0cmluZygzLGRlcHQpOw0KICAgICAgICAgICAgcHMuc2V0SW50KDQsY3IpOw0KICAgICAgICAgICAgbiA9IHBzLmV4ZWN1dGVVcGRhdGUoKTsNCiAgICAgICAgfSBjYXRjaCAoU1FMRXhjZXB0aW9uIGUpIHsNCiAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbihlLmdldE1lc3NhZ2UoKSk7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gKG4pOw0KICAgIH0NCiAgICANCiAgICBwdWJsaWMgc3RhdGljIGludCByZW1vdmVDb3Vyc2UoQ29ubmVjdGlvbiBjb25uLCBpbnQgY2lkKSANCiAgICB7DQogICAgICAgIGludCBuID0gMDsNCg0KICAgICAgICB0cnkgew0KICAgICAgICAgICAgU3RyaW5nIHVwZGF0ZVNRTCA9ICJERUxFVEUgRlJPTSBDb3Vyc2VzIFdIRVJFIGNpZCA9ID8iOw0KICAgICAgICAgICAgUHJlcGFyZWRTdGF0ZW1lbnQgcHMgPSBjb25uLnByZXBhcmVTdGF0ZW1lbnQodXBkYXRlU1FMKTsNCiAgICAgICAgICAgIHBzLnNldEludCgxLGNpZCk7DQogICAgICAgICAgICBuID0gcHMuZXhlY3V0ZVVwZGF0ZSgpOw0KICAgICAgICB9IGNhdGNoIChTUUxFeGNlcHRpb24gZSkgew0KICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKGUuZ2V0TWVzc2FnZSgpKTsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiAobik7DQogICAgfQ0KICAgIA0KICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBwcmludFJlc3VsdFNldCAoUmVzdWx0U2V0IHJzKQ0KICAgIHsNCiAgICAgICAgdHJ5IHsNCiAgICAgICAgICAgIFJlc3VsdFNldE1ldGFEYXRhIHJzbWQgPSBycy5nZXRNZXRhRGF0YSgpOw0KICAgICAgICAgICAgaW50IGNvbHVtbnNOdW1iZXIgPSByc21kLmdldENvbHVtbkNvdW50KCk7DQogICAgICAgICAgICB3aGlsZSAocnMubmV4dCgpKSB7DQogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gY29sdW1uc051bWJlcjsgaSsrKSB7DQogICAgICAgICAgICAgICAgICAgIGlmIChpID4gMSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludCgiLCAgIik7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgU3RyaW5nIGNvbHVtblZhbHVlID0gcnMuZ2V0U3RyaW5nKGkpOw0KICAgICAgICAgICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50KGNvbHVtblZhbHVlICsgIiAiICsgcnNtZC5nZXRDb2x1bW5OYW1lKGkpKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCIiKTsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgd2hpbGUgKHJzLm5leHQoKSkgew0KICAgICAgICAgICAgICAgIFN0cmluZyB0aXRsZSA9IHJzLmdldFN0cmluZygidGl0bGUiKTsNCiAgICAgICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4odGl0bGUpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9IGNhdGNoIChTUUxFeGNlcHRpb24gZSkgew0KICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKGUuZ2V0TWVzc2FnZSgpKTsNCiAgICAgICAgfQ0KICAgIH0NCiAgICANCiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSANCiAgICB7DQogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiY29ubmVjdGluZyB0byBzcWxpdGUgZGIuLi4iKTsNCiAgICAgICAgDQogICAgICAgIFN0cmluZyBzcWxpdGVEQiA9ICJjb3Vyc2VEQi5kYiI7DQogICAgICAgIENvbm5lY3Rpb24gY29ubiA9IGNvbm5lY3QgKHNxbGl0ZURCKTsNCiAgICAgICAgDQogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigicmV0cmlldmluZyBhbGwgY291cnNlcy4uLiIpOw0KICAgICAgICBwcmludFJlc3VsdFNldCAocmV0cmlldmVDb3Vyc2VzIChjb25uKSk7DQogICAgICAgIA0KICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oInJlbW92aW5nIGNvdXJzZSBjaWQgPSA0MDQuLi4iKTsNCiAgICAgICAgcmVtb3ZlQ291cnNlIChjb25uLCA0MDQpOw0KICAgICAgICANCiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJhZGRpbmcgbmV3IGNvdXJzZS4uLiIpOw0KICAgICAgICBhZGRDb3Vyc2UgKGNvbm4sIDQwNCwgIlRoZW9yeSBvZiBDb21wdXRhdGlvbiIsICJDUyIsIDMpOw0KICAgICAgICANCiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJyZXRyaWV2aW5nIG5ldyBjb3Vyc2UuLi4iKTsNCiAgICAgICAgcHJpbnRSZXN1bHRTZXQgKHJldHJpZXZlQ291cnNlIChjb25uLCA0MDQpKTsNCiAgICB9DQp9DQoNCmBgYA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgQ29uY2x1c2lvbg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgRmlsZXMgJiBSZXNvdXJjZXMNCg0KYGBge3IgemlwRmlsZXMsIGVjaG89RkFMU0V9DQp6aXBOYW1lID0gc3ByaW50ZigiTGVzc29uRmlsZXMtJXMtJXMuemlwIiwgDQogICAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwNCiAgICAgICAgICAgICAgICAgcGFyYW1zJG51bWJlcikNCg0KdGV4dEFMaW5rID0gcGFzdGUwKCJBbGwgRmlsZXMgZm9yIExlc3NvbiAiLCANCiAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwiLiIscGFyYW1zJG51bWJlcikNCg0KIyBkb3dubG9hZEZpbGVzTGluaygpIGlzIGluY2x1ZGVkIGZyb20gX2luc2VydDJEQi5SDQprbml0cjo6cmF3X2h0bWwoZG93bmxvYWRGaWxlc0xpbmsoIi4iLCB6aXBOYW1lLCB0ZXh0QUxpbmspKQ0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBSZWZlcmVuY2VzDQoNCltUaGUgc3FsZGYgUGFja2FnZS4gUiBEb2N1bWVudGF0aW9uLl0oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3NxbGRmL3ZlcnNpb25zLzAuNC0xMSkNCg0KW0NvcHkgRGF0YSBGcmFtZSB0byBUYWJsZXM6IGRiV3JpdGVUYWJsZV0oaHR0cHM6Ly9kYmkuci1kYmkub3JnL3JlZmVyZW5jZS9kYndyaXRldGFibGUpDQoNCiMjIEVycmF0YQ0KDQpOb25lIGNvbGxlY3RlZCB5ZXQuIExldCB1cyBrbm93Lg0KDQpgYGB7PWh0bWx9DQo8c2NyaXB0IHNyYz0iaHR0cHM6Ly9mb3JtLmpvdGZvcm0uY29tL3N0YXRpYy9mZWVkYmFjazIuanMiIHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQogIG5ldyBKb3Rmb3JtRmVlZGJhY2soew0KICAgIGZvcm1JZDogIjIxMjE4NzA3Mjc4NDE1NyIsDQogICAgYnV0dG9uVGV4dDogIkZlZWRiYWNrIiwNCiAgICBiYXNlOiAiaHR0cHM6Ly9mb3JtLmpvdGZvcm0uY29tLyIsDQogICAgYmFja2dyb3VuZDogIiNGNTkyMDIiLA0KICAgIGZvbnRDb2xvcjogIiNGRkZGRkYiLA0KICAgIGJ1dHRvblNpZGU6ICJsZWZ0IiwNCiAgICBidXR0b25BbGlnbjogImNlbnRlciIsDQogICAgdHlwZTogZmFsc2UsDQogICAgd2lkdGg6IDcwMCwNCiAgICBoZWlnaHQ6IDUwMCwNCiAgICBpc0NhcmRGb3JtOiBmYWxzZQ0KICB9KTsNCjwvc2NyaXB0Pg0KYGBgDQpgYGB7ciBjb2RlPXhmdW46OnJlYWRfdXRmOChwYXN0ZTAoaGVyZTo6aGVyZSgpLCcvUi9fZGVwbG95S25pdC5SJykpLCBpbmNsdWRlID0gRkFMU0V9DQpgYGANCg==