import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; public class UserFrontend { public static void main(String[] agrs) { String dbname = ""; // Input your UiO-username String user = ""; // Input your UiO-username + _priv String pwd = ""; // Input the password for the _priv-user you got in a mail // Connection details String connectionStr = "user=" + user + "&" + "port=5432&" + "password=" + pwd + ""; String host = "jdbc:postgresql://dbpg-ifi-kurs01.uio.no"; String connectionURL = host + "/" + dbname + "?sslmode=require&ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&" + connectionStr; try { // Load driver for PostgreSQL Class.forName("org.postgresql.Driver"); // Create a connection to the database //Connection connection = DriverManager.getConnection(); Connection connection = DriverManager.getConnection(host + "/" + dbname + "?" + connectionStr); String username = null; while (username == null) { System.out.println("-- USER FRONTEND --"); System.out.println("Please choose an option:\n 1. Register\n 2. Login\n 3. Exit"); int ch = getIntFromUser("Option: ", false); if (ch == 1) { register(connection); // Register new user } else if (ch == 2) { username = login(connection); // Login existing user } else if (ch == 3) { return; // Exit program } } // Once logged in, allow user to search for products search(connection, username); } catch (SQLException|ClassNotFoundException ex) { System.err.println("Error encountered: " + ex.getMessage()); } } private static void register(Connection connection) throws SQLException { System.out.println(" -- REGISTER NEW USER --"); // Get credentials for new user String username = getStrFromUser("Username: "); String password = getStrFromUser("Password: "); String name = getStrFromUser("Name: "); String address = getStrFromUser("Address: "); // To execute queries, we need a PreparedStatement object, created by calling // the prepareStatement()-method with a query as argument. // We can use ? as a place holder for a value in PreparedStatements, // and then set them using setString(int, String), setInt(int, int), etc. // where the first argument is the index of the value to set, starting with 1. // If we do not use these placeholders, the program is susceptible to SQL injection attacks // More about this on next lecture. PreparedStatement statement = connection.prepareStatement("INSERT INTO ws.users(name, username, password, address) VALUES (?, ?, ?, ?);"); statement.setString(1, name); statement.setString(2, username); statement.setString(3, password); // NOTE: NEVER store passwords in plain text for an actual application!!! statement.setString(4, address); // To execute the query we have made above, simply call the execute()-method statement.execute(); System.out.println("New user " + username + " added!"); } private static String login(Connection connection) throws SQLException { System.out.println(" -- LOGIN --"); // Get login details String username = getStrFromUser("Username: "); String password = getStrFromUser("Password: "); PreparedStatement statement = connection.prepareStatement("SELECT username, password, name FROM ws.users WHERE username = ? AND password = ?;"); statement.setString(1, username); statement.setString(2, password); // To execute the SELECT-query, we can call executeQuery() on the // statement-object. This will return a ResultSet, an iterator-like object over the results. // A ResultSet has a pointer to one row of the result ResultSet rows = statement.executeQuery(); // However, the ResultSet does not point to a row initially // By calling next() we move the pointer to the next row in the // result, and to the first row if not called before // The next() method returns a boolean which is false if there is no more // rows in the result, and true otherwise if (!rows.next()) { // The query returned no results, thus the user-password pair does not exist in the DB System.out.println("Incorrect username or password."); return null; } else { // Query returned a result, thus correct username and password System.out.println("Welcome " + username); return username; } } private static void search(Connection connection, String username) throws SQLException { // We start by gathering input from user, defining the search System.out.println(" -- SEARCH --"); String name = getStrFromUser("Search: "); String category = getStrFromUser("Category: "); // We will now construct the search query based on the user's input String q = "SELECT p.pid, p.name, p.price, c.name AS category, p.description " + "FROM ws.products AS p INNER JOIN ws.categories AS c USING (cid)" + "WHERE p.name LIKE ?"; if (!category.equals("")) { q += " AND c.name = ?"; } q += ";"; PreparedStatement statement = connection.prepareStatement(q); statement.setString(1, '%' + name + '%'); if (!category.equals("")) { statement.setString(2, category); } // We can now execute the query using the executeQuery()-method (described above) ResultSet rows = statement.executeQuery(); if (!rows.next()) { // No row to move to, thus empty result set System.out.println("No results."); return; } // The user should be able to pick which product to order based on the product's pid System.out.println(" -- RESULTS --\n"); do { // To get values from the current row in the ResultSet // we use getString(int) for Strings, getFloat(int) for floats, etc. // The argument int denotes which column to get a value from, starting from index 1 System.out.println("===" + rows.getString(2) + "===\n" + "Product ID: " + rows.getInt(1) + "\n" + "Price: " + rows.getFloat(3) + "\n" + "Category: " + rows.getString(4)); if (!rows.getString(3).equals("NULL")) { System.out.println("Description: " + rows.getString(5)); } System.out.print("\n"); } while (rows.next()); // Now that we have made a search, we will allow the user to order products from the // search result orderProducts(connection, username); } private static void orderProducts(Connection connection, String username) { } /** * Utility method that gets an int as input from user * Prints the argument message before getting input * If second argument is true, the user does not need to give input and can leave * the field blank (resulting in a null) */ private static Integer getIntFromUser(String message, boolean canBeBlank) { while (true) { String str = getStrFromUser(message); if (str.equals("") && canBeBlank) { return null; } try { return Integer.valueOf(str); } catch (NumberFormatException ex) { System.out.println("Please provide an integer or leave blank."); } } } /** * Utility method that gets a String as input from user * Prints the argument message before getting input */ private static String getStrFromUser(String message) { Scanner s = new Scanner(System.in); System.out.print(message); return s.nextLine(); } }